1. Abstract

This analysis studies the relationships among health indicators and diabetes status via exploratory data analysis visualizations. It is based on a sample data from the Diabetes Health Indictors dataset (BRFSS 2015). We first use visualization methods to look at individual variable distributions and then examine associations between different types of variables like diabetes status and BMI through histograms, box plots and density plots. We also explored relations between numerical variables and categorical variables via box plots to illustrate how distributions of BMI vary across diabetes groups. We also looked at high dimensional relations using faceted and interactive plots. Together, these provided preliminary insights into the patterns of relationships that exist in the dataset and help explain factors associated with diabetes for further analysis.


2. Introduction

In the USA, diabetes impacts over 37 million Americans and 1 in 5 people with diabetes do not know they have it according to the CDC. Over 38% of the US population have pre-diabetes - a condition that increases the risk of developing type 2 diabetes. It is one of the most prevalent chronic diseases in the US Xie et al (2019) . This presents a public health issue that has economic burdens, increased mortality rates and other health complications. It is estimated that the economic burden of diabetes in the US is about $327 billion anually with the cost of care on the rise. With a rise in the number of diabetes cases in recent years and its economic burden, understanding of risk factors driving these numbers are essential to enable policies that intervene on this national health crises. Tracking of cases by the BRFSS is one way the US is using to curb diabetes prevalence and its associated risk factors and also to intervene on modifiable lifestyle choices. For more details, visit Diabetes Basics

The Behavioral Risk Factor Surveillance System (BRFSS) is a telephone survey conducted annually by the Center For Disease Control and Prevention (CDC) to collect uniform, state-specific data on US adults’ health-related risk behaviors, chronic health conditions like diabetes, and use of preventive services. The focus of the survey is to collect data on demographics and social determinants of health, mental health and well being, health risk behaviors, chronic health conditions and use of preventive services in the United States population. It is an important system that helps public health personnel to design policies and health programs that benefits states and local agencies. Data from the system and the current analysis is utilized in the identification of risk factors that contribute to chronic diseases and health disparities among different populations, etc. We will particularity, explore the ability to identify which feature variables in the data are associated with diabetes either alone or in combination with other risk factors and also use advance methods in machine learning to accurately predict which individuals have diabetes based on the risk factors reported in the literature.

  • Description of Data

    We will use the 2015 BRFSS data in our exploratory analysis of the feature variables in this dataset. The dataset contains clean data originating from the original dataset which contained 441, 455 individuals and has 330 features. The clean version contains 253,681 survey responses from the CDC’s BRFSS 2015. It contains 21 feature variables and obtained from the kaggle website Diabetes Health Indicators Dataset

  • Feature Variables

    The clean dataset (BRFSS2015) contains the following features

    • Target feature: a categorical feature indicating if an individual has diabetes or not, Diabetes_binary (0 = no diabetes, 1 = prediabetes or diabetes)

    • Independent variables

      • HighBP: a categorical feature (0 = no high BP, 1 = high BP)
      • HighChol: a categorical feature that indicates if an individual has high cholesterol (1 = Yes, 0 = No)
      • CholCheck: a categorical feature that indicates if an individual had their cholesterol checked in the past five years (1 = Yes, 0 = No)
      • BMI: Body Mass Index,a continuous numerical feature based on the measure of body fat based on height and weight
      • Smoker: a categorical feature that indicates if an individual has smoked at least 100 cigarettes in their lifetime (1 = Yes, 0 = No)
      • Stroke: a categorical feature that indicates if an individual has had a stroke (1 = Yes, 0 = No)
      • HeartDiseaseorAttack: a categorical feature that indicates if an individual has coronary heart disease or a heart attack (1 = Yes, 0 = No)
      • PhysActivity: a categorical feature that indicates if an individual has engaged in physical activity in the past 30 days (1 = Yes, 0 = No)
      • Fruits: a categorical feature that indicates if the individual consumes fruits at least once per day (1 = Yes, 0 = No)
      • Veggies: a categorical feature that indicates if the individual consumes vegetables at least once per day (1 = Yes, 0 = No)
      • HvyAlcoholConsump: a categorical feature that indicates heavy alcohol consumption (1 = Yes, 0 = No)
      • AnyHealthcare: a categorical feature that indicates if the individual has any kind of health care coverage (1 = Yes, 0 = No)
      • NoDocbcCost: a categorical feature that indicates if the individual could not see a doctor due to cost in the past 12 months (1 = Yes, 0 = No)
      • GenHlth: a categorical feature that indicates General health status (1 = Excellent, 2 = Very good, 3 = Good, 4 = Fair, 5 = Poor)
      • MentHlth: a numerical feature representing the number of days mental health was not good in the past 30 days
      • PhysHlth: a numerical numerical feature representing the number of days physical health was not good in the past 30 days
      • DiffWalk: a categorical indicates if the individual has serious difficulty walking or climbing stairs (1 = Yes, 0 = No)
      • Sex: a categorical feature that indicates the gender of an individual (1 = Male, 0 = Female)
      • Age: a categorical feature representing the age category of the individual (1 = 18–24, 2 = 25–29, 3 = 30–34, 4 = 35–39, 5 = 40–44, 6 = 45–49, 7 = 50–54, 8 = 55–59, 9 = 60–64, 10 = 65–69, 11 = 70–74, 12 = 75–79, 13 = 80 or older)
      • Education: a categorical variable that indicates Education level of the individual (1 = Never attended school or only kindergarten, 2 = Grades 1 through 8 (Elementary), 3 = Grades 9 through 11 (Some high school, no diploma), 4 = Grade 12 or GED (High school graduate), 5 = College 1 to 3 years (Some college or technical school), 6 = College 4 years or more (College graduate) )
      • Income: a categorical variable that indicates Income category of the individual ( 1 = Less than $10,000, 2 = $10,000 to $14,999, 3 = $15,000 to $19,999, 4 = $20,000 to $24,999, 5 = $25,000 to $34,999, 6 = $35,000 to $49,999, 7 = $50,000 to $74,999, 8 = $75,000 or more)


3. Distribution of Individual Features


To prepare the dataset for our analysis purpose, we utilized the sample function to create some missingness in our dataset. We randomly replaced 5% of all feature variables with missing values to make the dataset represent real world data which is often observed with missing values in variables. It is important to point out that since this is an already cleaned dataset, there are not much to be done in addressing issues like unlikely values ( extreme height or weight, etc, non standard response to questionnaires among others). We will utilize exploratory data analysis to uncover patterns and relationships in the dataset. Feature engineering will be applied where applicable to create new variables and a visual representation of the data will be provided to identify trends and feature variable distributions. Additionally, sub group visualizations will be presented that enlightens our understanding of how diabetes affects certain groups of people and which feature variables are associated with diabetes.

  • Individual analytic tasks - The following feature variables comprise of some of the risk factors that are reported to be associated with diabetes that will be studied.
    • BMI: BMI histogram showed positively skewed data while a box plot also showed outliers. The outliers were removed from the dataset that were 1.5 times lower or higher than the first and third quartiles. The plot of the data without the outliers showed a smoother distribution. BMI was re-categorized into Underweight, Normal, Overweight and Obese. Over 70% of the sample were either overweight or obese to help identify at risk populations and easier interpretation of the data and for trend identification. It was apparent that most of the participants where either over weight or obese.
# get data into R
#setwd("~")
#getwd()

library(dplyr)
#ddat <- read.csv("/Users/mkatuahene/Desktop/WCU/R-Machine Learning/Assignment/Week 2/diabetes_binary_health_indicators_BRFSS2015.csv", skip=0)
ddat <- read.csv("https://matuahene.github.io/STA552/Week%202/diabetes_binary_health_indicators_BRFSS2015.csv", skip=0)

#getwd()
# Categorize income variable
ddat$Income_cat <- cut(ddat$Income, 
                                    breaks = c(-Inf, 3, 5, 6, Inf), 
                                    labels = c("Low", "Medium", "High", "Very High"))

#table(ddat$Income , ddat$Income_cat )

ddat2 <-ddat
#colSums(is.na(ddat2))


# assign meaningful labels to Age
ddat2$Age <- factor(ddat2$Age, 
  levels = 1:13, 
  labels = c("18-24 yrs", "25-29 yrs", "30-34 yrs", "35-39 yrs", "40-44 yrs", 
             "45-49 yrs", "50-54 yrs", "55-59 yrs", "60-64 yrs", "65-69 yrs", 
             "70-74 yrs", "75-79 yrs", "80+ yrs"))



# BMI categories
ddat2 <- ddat2 %>%
  mutate(BMI_Cat = cut(BMI, 
                            breaks = c(0, 18.5, 24.9, 29.9, Inf), 
                            labels = c("Underweight", "Normal", "Overweight", "Obese")))



# YES/NO labels
ddat2 <- ddat2 %>%
  mutate(
    HighChol = recode(HighChol, "0" = "No", "1" = "Yes"),
    HighBP = recode(HighBP, "0" = "No", "1" = "Yes"),
    Smoker = recode(Smoker, "0" = "No", "1" = "Yes"),
    Stroke = recode(Stroke, "0" = "No", "1" = "Yes"),
    HeartDiseaseorAttack = recode(HeartDiseaseorAttack, "0" = "No", "1" = "Yes"),
    PhysActivity = recode(PhysActivity, "0" = "No", "1" = "Yes"),
    Fruits = recode(Fruits, "0" = "No", "1" = "Yes"),
    Veggies = recode(Veggies, "0" = "No", "1" = "Yes")
  )


#Diabetes status, Education and Income, etc labels
ddat2 <- ddat2 %>%
  mutate(
    Education = recode(Education, 
                       "1" = "No High School", 
                       "2" = "Some High School", 
                       "3" = "High School Graduate", 
                       "4" = "Some College", 
                       "5" = "College Graduate",
                       "6" = "College 4 years or more (College graduate)"),
    Income = recode(Income, 
                    "1" = "<$10K", 
                    "2" = "$10K-$15K", 
                    "3" = "$15K-$25K", 
                    "4" = "$25K-$35K", 
                    "5" = "$35K-$50K", 
                    "6" = "$50K-$75K", 
                    "7" = ">$75K",
                    .default = "Unknown"),
   Sex = recode(Sex, 
                  "1" = "Male", 
                  "0" = "Female",
                .default = "Unknown"),
   CholCheck = recode(CholCheck,
                      "1" = "Yes",
                      "0" = "No" ),
   
   DiffWalk = recode(DiffWalk,
                      "1" = "Yes",
                      "0" = "No" ),
  
   AnyHealthcare = recode(AnyHealthcare,
                      "1" = "Yes",
                      "0" = "No" ),

   NoDocbcCost = recode(NoDocbcCost,
                      "1" = "Yes",
                      "0" = "No" ),
  HvyAlcoholConsump = recode(HvyAlcoholConsump,
                      "1" = "Yes",
                      "0" = "No" ),
    Diabetes_binary = recode(Diabetes_binary, 
                            "0" = "No Diabetes", 
                            "1" = "Has Diabetes"),
  
  GenHlth = recode(GenHlth,
                  "1" = "Excellent",
                   "2" = "Very Good",
                   "3" = "Good",
                   "4" = "Fair",
                   "5" = "Poor",
                   .default = "Unknown")
  )



#table (ddat2$Income)
#unique(ddat2$Income)

# create some missing data points 
# Define the percentage of missing values 
missing_percentage <- 0.05

# Get total number of rows
total_rows <- nrow(ddat2)

# Apply missing values to all variables
ddat2 <- ddat2 %>%
  mutate(across(everything(), ~ {
    miss_id <- sample(1:total_rows, size = round(missing_percentage * total_rows), replace = FALSE)
    .[miss_id] <- NA  # Assign NA to selected rows
    .
  }))




# overall summary of variables
library(summarytools)
dfSummary(ddat2)

#table(ddat2$Age)
#table(ddat2$BMI_Cat)
#summary (ddat2$BMI)
# get data into R
#BMI variable
library(ggplot2)
library(gridExtra)
library(grid)
bmi1 <- ggplot(ddat2, aes(x = BMI)) +
  geom_histogram(binwidth = 2, fill = "steelblue", color = "black", alpha = 0.7) +
  labs(title = "BMI Distribution", x = "BMI", y = "Count") +
  theme_minimal()

bmi2 <- ggplot(ddat2, aes(x = BMI)) +
  geom_density(fill = "lightblue", alpha = 0.6) +
  labs(title = "Density Plot of BMI", x = "BMI", y = "Density") +
  theme_minimal()

bmi3 <- ggplot(ddat2, aes(y = BMI)) +
  geom_boxplot(fill = "tomato", alpha = 0.7, outlier.color = "red") +
  labs(title = "Boxplot of BMI", y = "BMI") +
  theme_minimal()

grid.arrange(bmi1, bmi2, bmi3, ncol = 2, top = textGrob("Overview of BMI", gp = gpar(fontsize = 16, fontface = "bold"))) 

#check skewness of BMI
library(e1071)
skewness(ddat2$BMI, na.rm=TRUE) 
skewness(ddat2$BMI, na.rm=TRUE) 

# remove BMI outliers
Q1 <- quantile(ddat2$BMI, 0.25, na.rm = TRUE)
Q3 <- quantile(ddat2$BMI, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1

# Define acceptable range
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR

# Remove outliers
ddat3 <- ddat2[ddat2$BMI >= lower_bound & ddat2$BMI <= upper_bound, ]



#plot of BMI with outliers removed: ddat3 now contains data with no outliers
bmi12 <- ggplot(ddat3, aes(x = BMI)) +
  geom_histogram(binwidth = 2, fill = "steelblue", color = "black", alpha = 0.7) +
  labs(title = "BMI Distribution", x = "BMI", y = "Count") +
  theme_minimal()

bmi22 <- ggplot(ddat3, aes(x = BMI)) +
  geom_density(fill = "lightblue", alpha = 0.6) +
  labs(title = "Density Plot of BMI", x = "BMI", y = "Density") +
  theme_minimal()

bmi32 <- ggplot(ddat3, aes(y = BMI)) +
  geom_boxplot(fill = "tomato", alpha = 0.7, outlier.color = "red") +
  labs(title = "Boxplot of BMI", y = "BMI") +
  theme_minimal()

grid.arrange(bmi12, bmi22, bmi32, ncol = 2, top = textGrob("Overview of BMI with no outliers", gp = gpar(fontsize = 16, fontface = "bold"))) 

#categorized BMI bar chart
bmigrp<- ggplot(ddat3 %>% filter(!is.na(BMI_Cat)), aes(x = BMI_Cat)) +
  geom_bar(fill = "lightblue" , width = 0.6) +
  labs(title = "BMI Categories Distribution",
       x = "BMI category",
       y = "Count"
       ) +
  theme_classic() +
  theme(plot.margin = margin(2, 2, 2, 2) )
  
bmigrp

  • Diabetes Status: In the sample, majority of the participants did not have diabetes(86%). Only a smaller proportion where diabetic or had pre-diabetes. This suggests low prevalence of diabetes in our sample.
  • Mental Health: Histogram and density plots showed few people had few days with poor mental health the last 30 days (mean = approximately 3 days of bad mental health days). Outliers were replaced with mean values.
  • Physical Health in last 30 days distribution showed outliers and these values were replaced with the mean.
  • General Health Status: Most people reported very good or good health status overall with skewness observed towards poor health. and so no special changes will be applied to the variable.
  • Income variable was negatively skewed. Most participants earned higher income. The variable is categorized into Low, Medium, and High income levels.
  • Sex: More females participated in the sample data than males.
  • Age: Distribution of age was such that majority of participants were beyond 40 years old. This suggests that most participants were older and age should controlled for in any analysis.
  • Education: Most of the participants had a high school diploma or higher (over 80%).
  • High blood Pressure and High Cholesterol: More participants did not have high blood pressure and more did not have any cholesterol checks in the last 5 years.
  • Smoker: About 44% of the participants smoked at least 100 cigarettes in their entire lifetime. Considering how smoking affects our health and with such many in sample, controlling for this variable in our analysis and exploring how this variable interacts with others to impact diabetes will be studied.
  • Heavy Alcohol consumption - both men and women reported they are not heavy drinkers but these could be incorrect representation due to the fact that they may report as not heavy drinkers for socially desirable responses and expectations. The analysis can be conducted for men and women separately and for those who reported as heavy drinkers to uncover hidden relations.
  • Heart disease/attack was not prevalent in our sample. But we know that diabetes impacts the heart function, it will be interesting to see if those who had diabetes reported to ave had any of these conditions.
  • Stroke: Most people had never been told they had diabetes (95%).
  • Other variables: Most people did not have difficulty walking up the stairs, were physically active in the past 30 days, had some form of health insurance and could see a doctor when needed, consumed vegetables once or more times a day, but slightly more did not consume fruits at the same rate as vegetables.
# Diabetes Status
ggplot(ddat3 %>% filter(!is.na(Diabetes_binary)), aes(x = factor(Diabetes_binary))) +
  geom_bar(fill = "lightblue" , width = 0.4) +
  labs(title = "Diabetes Status",
       x = "Diabetes Status",
       y = "Count"
       ) +
  theme_classic()+
  theme(plot.margin = margin(2, 2, 2, 2) )

#Percentages within diabetes
Diab.percentages <- ddat3 %>%
  count(Diabetes_binary) %>%
  mutate(Percentage = n / sum(n) * 100)
Diab.percentages

#Mental Health Variables
summary(ddat3$MentHlth)
menh1 <- ggplot(ddat2, aes(x = MentHlth)) +
  geom_density(fill = "yellow", alpha = 0.6) +
  labs(title = "Density Plot of not good mental health days", x = "Mental Health", y = "Density") +
  theme_minimal()


menh2  <- ggplot(ddat3, aes(x = MentHlth)) +
  geom_histogram(binwidth = 2, fill = "yellow", color = "black", alpha = 0.7) +
  labs(title = "Histogram of not good mental health days", x = "Days", y = "Count") +
  theme_minimal()


menh3 <- ggplot(ddat3, aes(y = MentHlth)) +
  geom_boxplot(fill = "yellow", alpha = 0.7, outlier.color = "red") +
  labs(title = "Boxplot of Number of days Mental health was not good", y = "Mental Health Days") +
  theme_minimal()


grid.arrange(menh1, menh2, menh3, ncol = 2, top = textGrob("Overview of Mental Health in Past 30 Days", gp = gpar(fontsize = 16, fontface = "bold"))) 

# Define a function to replace outliers with the mean
replace_outliers_with_mean <- function(x) {
  Q1 <- quantile(x, 0.25, na.rm = TRUE)
  Q3 <- quantile(x, 0.75, na.rm = TRUE)
  IQR <- Q3 - Q1
  
  # Define lower and upper bounds
  lower_bound <- Q1 - 1.5 * IQR
  upper_bound <- Q3 + 1.5 * IQR
  
  # Replace outliers with the mean
  x[x < lower_bound | x > upper_bound] <- mean(x, na.rm = TRUE)
  
  return(x)
}

# Apply the function to mental health to replace outliers with mean value
ddat3$MentHlth <- replace_outliers_with_mean(ddat3$MentHlth)

#Physical Health histogram
Ph  <- ggplot(ddat3, aes(x = PhysHlth)) +
  geom_histogram(binwidth = 2, fill = "steelblue", color = "black", alpha = 0.7) +
  labs(title = "Physical Health Days", x = "Days", y = "Count") +
  theme_minimal()
#Ph

# Apply the function to mental health to replace outliers with mean value
ddat3$PhysHlth <- replace_outliers_with_mean(ddat3$PhysHlth)

#categorized General Health bar chart
ddat3 <- ddat3 %>%
  mutate(GenHlth = factor(GenHlth, 
                          levels = c("Poor", "Fair", "Good", "Very Good", "Excellent"), 
                          ordered = TRUE))  
Gh <- ggplot(ddat3 %>% filter(!is.na(GenHlth)), aes(x = GenHlth)) +
  geom_bar(fill = "blue", width =0.4) +
  labs(title = "General Health Status",
       x = "General Health",
       y = "Count"
       ) +
  scale_x_discrete(expand = c(0.1, 0.1))+
  theme_classic()
Gh

#categorized Sex chart
Sex <- ggplot(ddat3 %>% filter(!is.na(Sex)), aes(x = Sex)) +
  geom_bar(fill = "blue") +
  labs(title = "Gender",
       x = "Gender",
       y = "Count"
       ) +
  theme_classic()
#Sex
unique(ddat3$Sex);

# Age Groups
Age <- ggplot(ddat2 %>% filter(!is.na(Age)), aes(x = Age)) +
  geom_bar(fill = "blue") +
  labs(title = "Age group Bar Chart",
       x = "Age Group",
       y = "Count"
       ) +
  theme_classic()
#Age

Age.percentages <- ddat %>%
  count(Age) %>%
  mutate(Percentage = n / sum(n) * 100)
Age.percentages

# Education
Edu.percentages <- ddat %>%
  count(Education) %>%
  mutate(Percentage = n / sum(n) * 100)
Edu.percentages

# Smoker
Smoke.percentages <- ddat %>%
  count(Smoker) %>%
  mutate(Percentage = n / sum(n) * 100)
Smoke.percentages

# Stroke
Stroke.percentages <- ddat %>%
  count(Stroke) %>%
  mutate(Percentage = n / sum(n) * 100)
Stroke.percentages


4. Relationship between Features - Bivariate


We will now explore and have visualizations of relationships among several variables in our sample data. We will be looking at visuals for two or more numerical feature variables, categorical variables and visuals that look combinations of these to aid in our understanding of the data and how it influences our understanding of how to approach analysis of the data.

  • Diabetes and BMI plots : The box plot showing the diabetes and BMI plot shows the median BMI in the diabetic group is higher suggests relationship between these 2 variables. Additionally, the density plot shows higher BMI in the diabetic group than the non-diabetic group.
  • Diabetes and Physical Activity plot: The bivariate plot shows that while the distribution of physical activity in the past 30 days is similar, far less
    diabetic people were physically active in the last 30 days.
########## two variable relationships

# diabetes and BMI
 
ggplot(ddat3%>% filter(!is.na(Diabetes_binary)), aes(x = factor(Diabetes_binary), y = BMI, fill = factor(Diabetes_binary))) +
  geom_boxplot() +
  labs(title = "BMI Distribution by Diabetes Status",
       x = "Diabetes Status",
       y = "BMI") +
  scale_fill_manual(values = c("red", "green")) +
  theme_classic()+
  theme(legend.title = element_blank())

ggplot(ddat3%>% filter(!is.na(Diabetes_binary)), aes(x = BMI, fill = factor(Diabetes_binary))) +
  geom_density(alpha = 0.5) +
  labs(title = "BMI Density Plot by Diabetes Status",
       x = "BMI",
       y = "Density") +
  scale_fill_manual(values = c("red", "green")) +
  theme_minimal()+
  theme(legend.title = element_blank())

#diabetes and physical health

ggplot(ddat3%>% filter(!is.na(Diabetes_binary) & !is.na(PhysActivity)), aes(x = factor(Diabetes_binary), fill = factor(PhysActivity))) +
  geom_bar(position = "dodge") +
  labs(title = "Grouped Bar Plot of Diabetes Status and Physical Activity in pas 30 days",
       x = "Diabetes Status",
       y = "Count") +
  scale_fill_manual(values = c("blue", "red", "green")) +
  guides(fill = guide_legend(title = "Pysically Active last 30 days")) +
  theme_classic()

#colnames(ddat3)
#correlation plot of numerical variables
library(ggcorrplot)
select_vars <- c("PhysHlth", "MentHlth", "GenHlth", "BMI")
corr_matrix <- cor(ddat %>% select(all_of(select_vars)), use = "complete.obs")

library(ggplot2)
library(reshape2)

# Convert matrix to long format
corr_melt <- melt(corr_matrix)

# Plot heatmap
# Plot with text labels
cor1 <- ggplot(corr_melt, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile() +
  geom_text(aes(label = round(value, 2)), color = "black", size = 4) +  # Add values
  scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) +
  theme_minimal() +
  labs(title = "Correlation Heatmap", fill = "Correlation") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

#install.packages("corrplot")
library(corrplot)

corrplot(corr_matrix, method = "color", type = "upper",
         col = colorRampPalette(c("blue", "white", "red"))(200),
         tl.cex = 0.7, tl.col = "black",
         addCoef.col = "black", number.cex = 0.8)  # Add values

#install.packages("plotly")
library(ggplot2)
library(plotly)
unique(ddat3$Income_cat)
[1] Low       Very High <NA>      Medium    High     
Levels: Low Medium High Very High
mycolors <- c("Low" = "red", "Medium" = "orange", "High" = "green", "Very High" = "blue")

ggplotly_density <- ddat3%>% filter(!is.na(Income_cat) & !is.na(Diabetes_binary))  %>% 
  ggplot(aes(x = BMI, color = Income_cat, fill = Income_cat)) +
  geom_density(linewidth = 0.75, alpha = 0.6) +
  xlab("BMI Index") + 
  labs(color = "Income Groups", fill = "Income Groups") +
  ggtitle("Density Curve of BMI across Income Groups") +
  scale_color_manual(values = mycolors) +  # Custom line colors
  scale_fill_manual(values = mycolors) +  # Custom fill colors
           theme(plot.margin = unit(c(2,1,2,1), "cm"),
                plot.title = element_text(hjust = 0.5))  + 
  facet_wrap(~ Diabetes_binary)  # Split by diabetes status

ggplotly(ggplotly_density)
mycolors.n <- c("Poor" = "red", "Fair" = "orange", "Good" = "green", "Very Good" = "blue", "Excellent" = "lightblue")
ggplotly_density.n <- ddat3%>% filter(!is.na(GenHlth) & !is.na(Diabetes_binary))  %>% 
  ggplot(aes(x = BMI, color = GenHlth, fill = GenHlth)) +
  geom_density(linewidth = 0.75, alpha = 0.6) +
  xlab("BMI Index") + 
  labs(color = "General Health", fill = "General Health") +
  ggtitle("Density Curve of BMI across General Health") +
  scale_color_manual(values = mycolors.n) +  # Custom line colors
  scale_fill_manual(values = mycolors.n) +  # Custom fill colors
           theme(plot.margin = unit(c(2,1,2,1), "cm"),
                plot.title = element_text(hjust = 0.5))  + 
  facet_wrap(~ Diabetes_binary)  # Split by diabetes status

ggplotly(ggplotly_density.n)


5. Relationship between Features - Mutlivariate


The density plot of BMI and Income groups shows that BMI is highest in more participants in the low and medium income groups. And participants in the very high income group are among those with BMI less than 30 or healthier. When the plot is split by diabetes status, we observed similar distribution but we see that variance in the income groups is not as distinct for high and very high groups. While higher BMI is comon in all diabetics, it is more common in the Low and Medium income groups and indicates some variability in the the diabetic group. Similar patterns were observed among general health status with those in the poor health status also with higher BMI both in the diabetic and non-diabetic groups. The shift in peaks in both density plots suggests associations between diabetes and BMI which differs among different income and health groups.

LS0tCnRpdGxlOiAiSWRlbnRpZmljYXRpb24gb2YgRmFjdG9ycyBBc3NvY2ljYXRlZCB3aXRoIERpYWJldGVzIGluIHRoZSBVU0EiCiNzdWJ0aXRsZTogIkJlaGF2aW9yYWwgUmlzayBGYWN0b3IgU3VydmVpbGxhbmNlIFN5c3RlbSAoQlJGU1MpIgphdXRob3I6ICJNZXJjeSBBdHVhaGVuZSIgCmRhdGU6ICJGZWJydWFyeSA1LCAyMDI1IgphZmZpbGlhdGlvbjogIldlc3QgQ2hlc3RlciBVbml2ZXJzaXR5IG9mIFBlbm5zeWx2YW5pYSwgRGVwYXJ0bWVudCBvZiBTdGF0aXN0aWNzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICB0b2NfZmxvYXQ6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdG9jX2NvbGxhcHNlZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgc21vb3RoX3Njcm9sbDogeWVzCiAgICB0aGVtZTogbHVtZW4KIAogIHdvcmRfZG9jdW1lbnQ6IAogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgZmlnX2NhcHRpb246IHllcwogICAga2VlcF9tZDogeWVzCiAgcGRmX2RvY3VtZW50OiAKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIGZpZ193aWR0aDogMwogICAgZmlnX2hlaWdodDogMwplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCmBgYHs9aHRtbH0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CgovKiBDYXNjYWRpbmcgU3R5bGUgU2hlZXRzIChDU1MpIGlzIGEgc3R5bGVzaGVldCBsYW5ndWFnZSB1c2VkIHRvIGRlc2NyaWJlIHRoZSBwcmVzZW50YXRpb24gb2YgYSBkb2N1bWVudCB3cml0dGVuIGluIEhUTUwgb3IgWE1MLiBpdCBpcyBhIHNpbXBsZSBtZWNoYW5pc20gZm9yIGFkZGluZyBzdHlsZSAoZS5nLiwgZm9udHMsIGNvbG9ycywgc3BhY2luZykgdG8gV2ViIGRvY3VtZW50cy4gKi8KCmgxLnRpdGxlIHsgIC8qIFRpdGxlIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiB0aGUgcmVwb3J0IHRpdGxlICovCiAgZm9udC1zaXplOiAyMnB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7Cn0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBhdXRob3JzICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogc3lzdGVtLXVpOwogIGNvbG9yOiBuYXZ5OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciB0aGUgZGF0ZSAgKi8KICBmb250LXNpemU6IDE4cHg7CiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIGZvbnQtd2VpZ2h0OiBib2xkOwp9CmgxIHsgLyogSGVhZGVyIDEgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBsZXZlbCAxIHNlY3Rpb24gdGl0bGUgICovCiAgICBmb250LXNpemU6IDE4cHg7CiAgICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGNlbnRlcjsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwp9CmgyIHsgLyogSGVhZGVyIDIgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBsZXZlbCAyIHNlY3Rpb24gdGl0bGUgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwp9CgoKaDMgeyAvKiBIZWFkZXIgMyAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgMyBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAxNHB4OwogICAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoNCB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiBsZXZlbCA0IHNlY3Rpb24gdGl0bGUgICovCiAgICBmb250LXNpemU6IDEycHg7CiAgICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9CgouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQoKcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0KCjwvc3R5bGU+CmBgYAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLgppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQogICBsaWJyYXJ5KGtuaXRyKQp9CmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKbGlicmFyeSh0aWR5dmVyc2UpCn0KaWYgKCFyZXF1aXJlKCJHR2FsbHkiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJHR2FsbHkiKQpsaWJyYXJ5KEdHYWxseSkKfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIAogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLgogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BCiAgICAgICAgICAgICAgICAgICAgICApICAKI3NldHdkKCJ+IikKI3NldHdkKCIvVXNlcnMvbWthdHVhaGVuZS9EZXNrdG9wL1dDVS9SLU1hY2hpbmUgTGVhcm5pbmcvQXNzaWdubWVudC9XZWVrIDIiKSAKYGBgCgpcCgojIyAxLiBBYnN0cmFjdApUaGlzIGFuYWx5c2lzIHN0dWRpZXMgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgaGVhbHRoIGluZGljYXRvcnMgYW5kIGRpYWJldGVzIHN0YXR1cyB2aWEgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyB2aXN1YWxpemF0aW9ucy4gSXQgaXMgYmFzZWQgb24gYSBzYW1wbGUgZGF0YSBmcm9tIHRoZSBEaWFiZXRlcyBIZWFsdGggSW5kaWN0b3JzIGRhdGFzZXQgKEJSRlNTIDIwMTUpLiBXZSBmaXJzdCB1c2UgdmlzdWFsaXphdGlvbiBtZXRob2RzIHRvIGxvb2sgYXQgaW5kaXZpZHVhbCB2YXJpYWJsZSBkaXN0cmlidXRpb25zIGFuZCB0aGVuIGV4YW1pbmUgYXNzb2NpYXRpb25zIGJldHdlZW4gZGlmZmVyZW50IHR5cGVzIG9mIHZhcmlhYmxlcyBsaWtlIGRpYWJldGVzIHN0YXR1cyBhbmQgQk1JIHRocm91Z2ggaGlzdG9ncmFtcywgYm94IHBsb3RzIGFuZCBkZW5zaXR5IHBsb3RzLiBXZSBhbHNvIGV4cGxvcmVkIHJlbGF0aW9ucyBiZXR3ZWVuIG51bWVyaWNhbCB2YXJpYWJsZXMgYW5kIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB2aWEgYm94IHBsb3RzIHRvIGlsbHVzdHJhdGUgaG93IGRpc3RyaWJ1dGlvbnMgb2YgQk1JIHZhcnkgYWNyb3NzIGRpYWJldGVzIGdyb3Vwcy4gV2UgYWxzbyBsb29rZWQgYXQgaGlnaCBkaW1lbnNpb25hbCByZWxhdGlvbnMgdXNpbmcgZmFjZXRlZCBhbmQgaW50ZXJhY3RpdmUgcGxvdHMuIFRvZ2V0aGVyLCB0aGVzZSBwcm92aWRlZCBwcmVsaW1pbmFyeSBpbnNpZ2h0cyBpbnRvIHRoZSBwYXR0ZXJucyBvZiByZWxhdGlvbnNoaXBzIHRoYXQgZXhpc3QgaW4gdGhlIGRhdGFzZXQgYW5kIGhlbHAgZXhwbGFpbiBmYWN0b3JzIGFzc29jaWF0ZWQgd2l0aCBkaWFiZXRlcyBmb3IgZnVydGhlciBhbmFseXNpcy4gIAoKClwKCiMjIDIuIEludHJvZHVjdGlvbgogIEluIHRoZSBVU0EsIGRpYWJldGVzIGltcGFjdHMgb3ZlciAzNyBtaWxsaW9uIEFtZXJpY2FucyBhbmQgMSBpbiA1IHBlb3BsZSB3aXRoIGRpYWJldGVzIGRvIG5vdCBrbm93IHRoZXkgaGF2ZSBpdCBhY2NvcmRpbmcgdG8gdGhlIENEQy4gT3ZlciAzOCUgb2YgdGhlIFVTIHBvcHVsYXRpb24gaGF2ZSBwcmUtZGlhYmV0ZXMgLSBhIGNvbmRpdGlvbiB0aGF0IGluY3JlYXNlcyB0aGUgcmlzayBvZiBkZXZlbG9waW5nIHR5cGUgMiBkaWFiZXRlcy4gSXQgaXMgb25lIG9mIHRoZSBtb3N0IHByZXZhbGVudCBjaHJvbmljIGRpc2Vhc2VzIGluIHRoZSBVUyA8YSAgIGhyZWY9Imh0dHBzOi8vd3d3LmNkYy5nb3YvcGNkL2lzc3Vlcy8yMDE5LzE5XzAxMDkuaHRtIiB0YXJnZXQ9Il9ibGFuayI+IFhpZSBldCBhbCAoMjAxOSk8L2E+IC4gVGhpcyBwcmVzZW50cyBhIHB1YmxpYyBoZWFsdGggaXNzdWUgdGhhdCBoYXMgZWNvbm9taWMgYnVyZGVucywgaW5jcmVhc2VkIG1vcnRhbGl0eSByYXRlcyBhbmQgb3RoZXIgaGVhbHRoIGNvbXBsaWNhdGlvbnMuIEl0IGlzIGVzdGltYXRlZCB0aGF0IHRoZSBlY29ub21pYyBidXJkZW4gb2YgZGlhYmV0ZXMgaW4gdGhlIFVTIGlzIGFib3V0ICQzMjcgYmlsbGlvbiBhbnVhbGx5IHdpdGggdGhlIGNvc3Qgb2YgY2FyZSBvbiB0aGUgcmlzZS4gV2l0aCBhIHJpc2UgaW4gdGhlIG51bWJlciBvZiBkaWFiZXRlcyBjYXNlcyBpbiByZWNlbnQgeWVhcnMgYW5kIGl0cyBlY29ub21pYyBidXJkZW4sIHVuZGVyc3RhbmRpbmcgb2YgcmlzayBmYWN0b3JzIGRyaXZpbmcgdGhlc2UgbnVtYmVycyBhcmUgZXNzZW50aWFsIHRvIGVuYWJsZSBwb2xpY2llcyB0aGF0IGludGVydmVuZSBvbiB0aGlzIG5hdGlvbmFsIGhlYWx0aCBjcmlzZXMuIFRyYWNraW5nIG9mIGNhc2VzIGJ5IHRoZSBCUkZTUyBpcyBvbmUgd2F5IHRoZSBVUyBpcyB1c2luZyB0byBjdXJiIGRpYWJldGVzIHByZXZhbGVuY2UgYW5kIGl0cyBhc3NvY2lhdGVkIHJpc2sgZmFjdG9ycyBhbmQgYWxzbyB0byBpbnRlcnZlbmUgb24gbW9kaWZpYWJsZSBsaWZlc3R5bGUgY2hvaWNlcy4gRm9yIG1vcmUgZGV0YWlscywgdmlzaXQgPGEgaHJlZj0iaHR0cHM6Ly93d3cuY2RjLmdvdi9kaWFiZXRlcy9hYm91dC9pbmRleC5odG1sP3V0bV9zb3VyY2U9Y2hhdGdwdC5jb20jY2RjX2Rpc2Vhc2VfYmFzaWNzX3F1aWNrX2ZhY3RzX2NhbGxvdXRfY2FsbG91dC1kaWFiZXRlcy1ieS10aGUtbnVtYmVycyIgdGFyZ2V0PSJfYmxhbmsiPkRpYWJldGVzIEJhc2ljczwvYT4gCgpUaGUgQmVoYXZpb3JhbCBSaXNrIEZhY3RvciBTdXJ2ZWlsbGFuY2UgU3lzdGVtIChCUkZTUykgaXMgYSB0ZWxlcGhvbmUgc3VydmV5IGNvbmR1Y3RlZCBhbm51YWxseSBieSB0aGUgQ2VudGVyIEZvciBEaXNlYXNlIENvbnRyb2wgYW5kIFByZXZlbnRpb24gKENEQykgdG8gY29sbGVjdCB1bmlmb3JtLCBzdGF0ZS1zcGVjaWZpYyBkYXRhIG9uIFVTIGFkdWx0cycgaGVhbHRoLXJlbGF0ZWQgcmlzayBiZWhhdmlvcnMsIGNocm9uaWMgaGVhbHRoIGNvbmRpdGlvbnMgbGlrZSBkaWFiZXRlcywgYW5kIHVzZSBvZiBwcmV2ZW50aXZlIHNlcnZpY2VzLiBUaGUgZm9jdXMgb2YgdGhlIHN1cnZleSBpcyB0byBjb2xsZWN0IGRhdGEgb24gZGVtb2dyYXBoaWNzIGFuZCBzb2NpYWwgZGV0ZXJtaW5hbnRzIG9mIGhlYWx0aCwgbWVudGFsIGhlYWx0aCBhbmQgd2VsbCBiZWluZywgaGVhbHRoIHJpc2sgYmVoYXZpb3JzLCBjaHJvbmljIGhlYWx0aCBjb25kaXRpb25zIGFuZCB1c2Ugb2YgcHJldmVudGl2ZSBzZXJ2aWNlcyBpbiB0aGUgVW5pdGVkIFN0YXRlcyBwb3B1bGF0aW9uLiBJdCBpcyBhbiBpbXBvcnRhbnQgc3lzdGVtIHRoYXQgaGVscHMgcHVibGljIGhlYWx0aCBwZXJzb25uZWwgdG8gZGVzaWduIHBvbGljaWVzIGFuZCBoZWFsdGggcHJvZ3JhbXMgdGhhdCBiZW5lZml0cyBzdGF0ZXMgYW5kIGxvY2FsIGFnZW5jaWVzLiBEYXRhIGZyb20gdGhlIHN5c3RlbSBhbmQgdGhlIGN1cnJlbnQgYW5hbHlzaXMgaXMgdXRpbGl6ZWQgaW4gdGhlIGlkZW50aWZpY2F0aW9uIG9mIHJpc2sgZmFjdG9ycyB0aGF0IGNvbnRyaWJ1dGUgdG8gY2hyb25pYyBkaXNlYXNlcyBhbmQgaGVhbHRoIGRpc3Bhcml0aWVzIGFtb25nIGRpZmZlcmVudCBwb3B1bGF0aW9ucywgZXRjLiBXZSB3aWxsIHBhcnRpY3VsYXJpdHksIGV4cGxvcmUgdGhlIGFiaWxpdHkgdG8gaWRlbnRpZnkgd2hpY2ggZmVhdHVyZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgYXJlIGFzc29jaWF0ZWQgd2l0aCBkaWFiZXRlcyBlaXRoZXIgYWxvbmUgb3IgaW4gY29tYmluYXRpb24gd2l0aCBvdGhlciByaXNrIGZhY3RvcnMgYW5kIGFsc28gdXNlIGFkdmFuY2UgbWV0aG9kcyBpbiBtYWNoaW5lIGxlYXJuaW5nIHRvIGFjY3VyYXRlbHkgcHJlZGljdCB3aGljaCBpbmRpdmlkdWFscyBoYXZlIGRpYWJldGVzIGJhc2VkIG9uIHRoZSByaXNrIGZhY3RvcnMgcmVwb3J0ZWQgaW4gdGhlIGxpdGVyYXR1cmUuIAoKCiogKipEZXNjcmlwdGlvbiBvZiBEYXRhKioKCiAgV2Ugd2lsbCB1c2UgdGhlIDIwMTUgQlJGU1MgZGF0YSBpbiBvdXIgZXhwbG9yYXRvcnkgYW5hbHlzaXMgb2YgdGhlIGZlYXR1cmUgdmFyaWFibGVzIGluIHRoaXMgZGF0YXNldC4gVGhlIGRhdGFzZXQgY29udGFpbnMgY2xlYW4gZGF0YSBvcmlnaW5hdGluZyBmcm9tIHRoZSBvcmlnaW5hbCBkYXRhc2V0IHdoaWNoIGNvbnRhaW5lZCA0NDEsIDQ1NSBpbmRpdmlkdWFscyBhbmQgaGFzIDMzMCBmZWF0dXJlcy4gVGhlIGNsZWFuIHZlcnNpb24gY29udGFpbnMgMjUzLDY4MSBzdXJ2ZXkgcmVzcG9uc2VzIGZyb20gdGhlIENEQydzIEJSRlNTIDIwMTUuIEl0IGNvbnRhaW5zIDIxIGZlYXR1cmUgdmFyaWFibGVzIGFuZCBvYnRhaW5lZCBmcm9tIHRoZSBrYWdnbGUgd2Vic2l0ZSA8YSAgIGhyZWY9Imh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvYWxleHRlYm91bC9kaWFiZXRlcy1oZWFsdGgtaW5kaWNhdG9ycy1kYXRhc2V0P3V0bV9zb3VyY2U9Y2hhdGdwdC5jb20mc2VsZWN0PWRpYWJldGVzX2IgICBpbmFyeV9oZWFsdGhfaW5kaWNhdG9yc19CUkZTUzIwMTUuY3N2IiB0YXJnZXQ9Il9ibGFuayI+RGlhYmV0ZXMgSGVhbHRoIEluZGljYXRvcnMgRGF0YXNldDwvYT4KCiogKipGZWF0dXJlIFZhcmlhYmxlcyoqCgogIFRoZSBjbGVhbiBkYXRhc2V0IChCUkZTUzIwMTUpIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgZmVhdHVyZXMKICAgKiAqKlRhcmdldCBmZWF0dXJlOioqIGEgY2F0ZWdvcmljYWwgZmVhdHVyZSBpbmRpY2F0aW5nIGlmIGFuIGluZGl2aWR1YWwgaGFzIGRpYWJldGVzIG9yIG5vdCwgRGlhYmV0ZXNfYmluYXJ5ICgwID0gbm8gZGlhYmV0ZXMsIDEgPSBwcmVkaWFiZXRlcyBvciBkaWFiZXRlcykKICAgCiAgICogKipJbmRlcGVuZGVudCB2YXJpYWJsZXMqKgogICAgICsgSGlnaEJQOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgKDAgPSBubyBoaWdoIEJQLCAxID0gaGlnaCBCUCkKICAgICArIEhpZ2hDaG9sOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgYW4gaW5kaXZpZHVhbCBoYXMgaGlnaCBjaG9sZXN0ZXJvbCAoMSA9IFllcywgMCA9IE5vKQogICAgICsgQ2hvbENoZWNrOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgYW4gaW5kaXZpZHVhbCBoYWQgdGhlaXIgY2hvbGVzdGVyb2wgY2hlY2tlZCBpbiB0aGUgcGFzdCBmaXZlIHllYXJzICgxID0gWWVzLCAwID0gTm8pCiAgICAgKyBCTUk6IEJvZHkgTWFzcyBJbmRleCxhIGNvbnRpbnVvdXMgbnVtZXJpY2FsIGZlYXR1cmUgYmFzZWQgb24gdGhlIG1lYXN1cmUgb2YgYm9keSBmYXQgYmFzZWQgb24gaGVpZ2h0IGFuZCB3ZWlnaHQKICAgICArIFNtb2tlcjogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIGFuIGluZGl2aWR1YWwgaGFzIHNtb2tlZCBhdCBsZWFzdCAxMDAgY2lnYXJldHRlcyBpbiB0aGVpciBsaWZldGltZSAoMSA9IFllcywgMCA9IE5vKQogICAgICsgU3Ryb2tlOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgYW4gaW5kaXZpZHVhbCBoYXMgaGFkIGEgc3Ryb2tlICgxID0gWWVzLCAwID0gTm8pCiAgICAgKyBIZWFydERpc2Vhc2VvckF0dGFjazogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIGFuIGluZGl2aWR1YWwgaGFzIGNvcm9uYXJ5IGhlYXJ0IGRpc2Vhc2Ugb3IgYSBoZWFydCBhdHRhY2sgKDEgPSBZZXMsIDAgPSBObykKICAgICArIFBoeXNBY3Rpdml0eTogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIGFuIGluZGl2aWR1YWwgaGFzIGVuZ2FnZWQgaW4gcGh5c2ljYWwgYWN0aXZpdHkgaW4gdGhlIHBhc3QgMzAgZGF5cyAoMSA9IFllcywgMCA9IE5vKQogICAgICsgRnJ1aXRzOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgdGhlIGluZGl2aWR1YWwgY29uc3VtZXMgZnJ1aXRzIGF0IGxlYXN0IG9uY2UgcGVyIGRheSAoMSA9IFllcywgMCA9IE5vKQogICAgICsgVmVnZ2llczogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIHRoZSBpbmRpdmlkdWFsIGNvbnN1bWVzIHZlZ2V0YWJsZXMgYXQgbGVhc3Qgb25jZSBwZXIgZGF5ICgxID0gWWVzLCAwID0gTm8pCiAgICAgKyBIdnlBbGNvaG9sQ29uc3VtcDogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGhlYXZ5IGFsY29ob2wgY29uc3VtcHRpb24gKDEgPSBZZXMsIDAgPSBObykKICAgICArIEFueUhlYWx0aGNhcmU6IGEgY2F0ZWdvcmljYWwgZmVhdHVyZSB0aGF0IGluZGljYXRlcyBpZiB0aGUgaW5kaXZpZHVhbCBoYXMgYW55IGtpbmQgb2YgaGVhbHRoIGNhcmUgY292ZXJhZ2UgKDEgPSBZZXMsIDAgPSBObykKICAgICArIE5vRG9jYmNDb3N0OiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgdGhlIGluZGl2aWR1YWwgY291bGQgbm90IHNlZSBhIGRvY3RvciBkdWUgdG8gY29zdCBpbiB0aGUgcGFzdCAxMiBtb250aHMgKDEgPSBZZXMsIDAgPSBObykKICAgICArIEdlbkhsdGg6IGEgY2F0ZWdvcmljYWwgZmVhdHVyZSB0aGF0IGluZGljYXRlcyBHZW5lcmFsIGhlYWx0aCBzdGF0dXMgKDEgPSBFeGNlbGxlbnQsIDIgPSBWZXJ5IGdvb2QsIDMgPSBHb29kLCA0ID0gRmFpciwgNSA9IFBvb3IpCiAgICAgKyBNZW50SGx0aDogYSBudW1lcmljYWwgZmVhdHVyZSByZXByZXNlbnRpbmcgdGhlIG51bWJlciBvZiBkYXlzIG1lbnRhbCBoZWFsdGggd2FzIG5vdCBnb29kIGluIHRoZSBwYXN0IDMwIGRheXMKICAgICArIFBoeXNIbHRoOiBhIG51bWVyaWNhbCBudW1lcmljYWwgZmVhdHVyZSByZXByZXNlbnRpbmcgdGhlIG51bWJlciBvZiBkYXlzIHBoeXNpY2FsIGhlYWx0aCB3YXMgbm90IGdvb2QgaW4gdGhlIHBhc3QgMzAgZGF5cwogICAgICsgRGlmZldhbGs6IGEgY2F0ZWdvcmljYWwgaW5kaWNhdGVzIGlmIHRoZSBpbmRpdmlkdWFsIGhhcyBzZXJpb3VzIGRpZmZpY3VsdHkgd2Fsa2luZyBvciBjbGltYmluZyBzdGFpcnMgKDEgPSBZZXMsIDAgPSBObykKICAgICArIFNleDogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIHRoZSBnZW5kZXIgb2YgYW4gaW5kaXZpZHVhbCAoMSA9IE1hbGUsIDAgPSBGZW1hbGUpCiAgICAgKyBBZ2U6IGEgY2F0ZWdvcmljYWwgZmVhdHVyZSByZXByZXNlbnRpbmcgdGhlIGFnZSBjYXRlZ29yeSBvZiB0aGUgaW5kaXZpZHVhbCAoMSA9IDE44oCTMjQsIDIgPSAyNeKAkzI5LCAzID0gMzDigJMzNCwgNCA9IDM14oCTMzksIDUgPSA0MOKAkzQ0LCA2ID0gNDXigJM0OSwgNyA9IDUw4oCTNTQsIDggPSA1NeKAkzU5LCA5ID0gICAgICAgICAgICA2MOKAkzY0LCAxMCA9IDY14oCTNjksIDExID0gNzDigJM3NCwgMTIgPSA3NeKAkzc5LCAxMyA9IDgwIG9yIG9sZGVyKQogICAgICsgRWR1Y2F0aW9uOiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIHRoYXQgaW5kaWNhdGVzIEVkdWNhdGlvbiBsZXZlbCBvZiB0aGUgaW5kaXZpZHVhbCAoMSA9IE5ldmVyIGF0dGVuZGVkIHNjaG9vbCBvciBvbmx5IGtpbmRlcmdhcnRlbiwgMiA9IEdyYWRlcyAxIHRocm91Z2ggOCAoRWxlbWVudGFyeSksIDMgPSAgICAgICAgR3JhZGVzIDkgdGhyb3VnaCAxMSAoU29tZSBoaWdoIHNjaG9vbCwgbm8gZGlwbG9tYSksIDQgPSBHcmFkZSAxMiBvciBHRUQgKEhpZ2ggc2Nob29sIGdyYWR1YXRlKSwgNSA9IENvbGxlZ2UgMSB0byAzIHllYXJzIChTb21lIGNvbGxlZ2Ugb3IgdGVjaG5pY2FsIHNjaG9vbCksIDYgPSBDb2xsZWdlIDQgICAgICAgIHllYXJzIG9yIG1vcmUgKENvbGxlZ2UgZ3JhZHVhdGUpICkKICAgICArIEluY29tZTogYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB0aGF0IGluZGljYXRlcyBJbmNvbWUgY2F0ZWdvcnkgb2YgdGhlIGluZGl2aWR1YWwgKCAxID0gTGVzcyB0aGFuICQxMCwwMDAsIDIgPSAgJDEwLDAwMCB0byAkMTQsOTk5LCAzID0gJDE1LDAwMCB0byAkMTksOTk5LCA0ID0gJDIwLDAwMCB0byAgICAgICAgICAgJDI0LDk5OSwgNSA9ICQyNSwwMDAgdG8gJDM0LDk5OSwgNiA9ICQzNSwwMDAgdG8gJDQ5LDk5OSwgNyA9ICQ1MCwwMDAgdG8gJDc0LDk5OSwgOCA9ICQ3NSwwMDAgb3IgbW9yZSkKClwKCiMjIDMuIERpc3RyaWJ1dGlvbiBvZiBJbmRpdmlkdWFsIEZlYXR1cmVzCgpcClRvIHByZXBhcmUgdGhlIGRhdGFzZXQgZm9yIG91ciBhbmFseXNpcyBwdXJwb3NlLCB3ZSB1dGlsaXplZCB0aGUgc2FtcGxlIGZ1bmN0aW9uIHRvIGNyZWF0ZSBzb21lIG1pc3NpbmduZXNzIGluIG91ciBkYXRhc2V0LiBXZSByYW5kb21seSByZXBsYWNlZCA1JSBvZiBhbGwgZmVhdHVyZSB2YXJpYWJsZXMgd2l0aCBtaXNzaW5nIHZhbHVlcyB0byBtYWtlIHRoZSBkYXRhc2V0IHJlcHJlc2VudCByZWFsIHdvcmxkIGRhdGEgd2hpY2ggaXMgb2Z0ZW4gb2JzZXJ2ZWQgd2l0aCBtaXNzaW5nIHZhbHVlcyBpbiB2YXJpYWJsZXMuICBJdCBpcyBpbXBvcnRhbnQgdG8gcG9pbnQgb3V0IHRoYXQgc2luY2UgdGhpcyBpcyBhbiBhbHJlYWR5IGNsZWFuZWQgZGF0YXNldCwgdGhlcmUgYXJlIG5vdCBtdWNoIHRvIGJlIGRvbmUgaW4gYWRkcmVzc2luZyBpc3N1ZXMgbGlrZSB1bmxpa2VseSB2YWx1ZXMgKCBleHRyZW1lIGhlaWdodCBvciB3ZWlnaHQsIGV0Yywgbm9uIHN0YW5kYXJkIHJlc3BvbnNlIHRvIHF1ZXN0aW9ubmFpcmVzIGFtb25nIG90aGVycykuIFdlIHdpbGwgdXRpbGl6ZSBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHRvIHVuY292ZXIgcGF0dGVybnMgYW5kIHJlbGF0aW9uc2hpcHMgaW4gdGhlIGRhdGFzZXQuIEZlYXR1cmUgZW5naW5lZXJpbmcgd2lsbCBiZSBhcHBsaWVkIHdoZXJlIGFwcGxpY2FibGUgdG8gY3JlYXRlIG5ldyB2YXJpYWJsZXMgYW5kIGEgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkYXRhIHdpbGwgYmUgcHJvdmlkZWQgdG8gaWRlbnRpZnkgdHJlbmRzIGFuZCBmZWF0dXJlIHZhcmlhYmxlIGRpc3RyaWJ1dGlvbnMuIEFkZGl0aW9uYWxseSwgc3ViIGdyb3VwIHZpc3VhbGl6YXRpb25zIHdpbGwgYmUgcHJlc2VudGVkIHRoYXQgZW5saWdodGVucyBvdXIgdW5kZXJzdGFuZGluZyBvZiBob3cgZGlhYmV0ZXMgYWZmZWN0cyBjZXJ0YWluIGdyb3VwcyBvZiBwZW9wbGUgYW5kIHdoaWNoIGZlYXR1cmUgdmFyaWFibGVzIGFyZSBhc3NvY2lhdGVkIHdpdGggZGlhYmV0ZXMuIAoKKiAqKkluZGl2aWR1YWwgYW5hbHl0aWMgdGFza3MqKiAtClRoZSBmb2xsb3dpbmcgZmVhdHVyZSB2YXJpYWJsZXMgY29tcHJpc2Ugb2Ygc29tZSBvZiB0aGUgcmlzayBmYWN0b3JzIHRoYXQgYXJlIHJlcG9ydGVkIHRvIGJlIGFzc29jaWF0ZWQgd2l0aCBkaWFiZXRlcyB0aGF0IHdpbGwgYmUgc3R1ZGllZC4KICArIEJNSTogQk1JIGhpc3RvZ3JhbSBzaG93ZWQgcG9zaXRpdmVseSBza2V3ZWQgZGF0YSB3aGlsZSBhIGJveCBwbG90IGFsc28gc2hvd2VkIG91dGxpZXJzLiBUaGUgb3V0bGllcnMgd2VyZSByZW1vdmVkIGZyb20gdGhlIGRhdGFzZXQgdGhhdCB3ZXJlIDEuNSB0aW1lcyBsb3dlciBvciBoaWdoZXIgdGhhbiB0aGUgICAgIGZpcnN0IGFuZCB0aGlyZCBxdWFydGlsZXMuIFRoZSBwbG90IG9mIHRoZSBkYXRhIHdpdGhvdXQgdGhlIG91dGxpZXJzIHNob3dlZCBhIHNtb290aGVyIGRpc3RyaWJ1dGlvbi4KICAgIEJNSSB3YXMgcmUtY2F0ZWdvcml6ZWQgaW50byBVbmRlcndlaWdodCwgTm9ybWFsLCBPdmVyd2VpZ2h0IGFuZCBPYmVzZS4gT3ZlciA3MCUgb2YgdGhlIHNhbXBsZSB3ZXJlIGVpdGhlciBvdmVyd2VpZ2h0IG9yIG9iZXNlIHRvIGhlbHAgaWRlbnRpZnkgYXQgcmlzayBwb3B1bGF0aW9ucyBhbmQgZWFzaWVyIGludGVycHJldGF0aW9uIG9mIHRoZSBkYXRhIGFuZCBmb3IgdHJlbmQgaWRlbnRpZmljYXRpb24uIEl0IHdhcyBhcHBhcmVudCB0aGF0IG1vc3Qgb2YgdGhlIHBhcnRpY2lwYW50cyB3aGVyZSBlaXRoZXIgb3ZlciB3ZWlnaHQgb3Igb2Jlc2UuCgpgYGB7ciBjbGVhbmRhdGEsIHJlc3VsdHM9J2hpZGUnfQojIGdldCBkYXRhIGludG8gUgojc2V0d2QoIn4iKQojZ2V0d2QoKQoKbGlicmFyeShkcGx5cikKI2RkYXQgPC0gcmVhZC5jc3YoIi9Vc2Vycy9ta2F0dWFoZW5lL0Rlc2t0b3AvV0NVL1ItTWFjaGluZSBMZWFybmluZy9Bc3NpZ25tZW50L1dlZWsgMi9kaWFiZXRlc19iaW5hcnlfaGVhbHRoX2luZGljYXRvcnNfQlJGU1MyMDE1LmNzdiIsIHNraXA9MCkKZGRhdCA8LSByZWFkLmNzdigiaHR0cHM6Ly9tYXR1YWhlbmUuZ2l0aHViLmlvL1NUQTU1Mi9XZWVrJTIwMi9kaWFiZXRlc19iaW5hcnlfaGVhbHRoX2luZGljYXRvcnNfQlJGU1MyMDE1LmNzdiIsIHNraXA9MCkKCiNnZXR3ZCgpCiMgQ2F0ZWdvcml6ZSBpbmNvbWUgdmFyaWFibGUKZGRhdCRJbmNvbWVfY2F0IDwtIGN1dChkZGF0JEluY29tZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgMywgNSwgNiwgSW5mKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIsICJWZXJ5IEhpZ2giKSkKCiN0YWJsZShkZGF0JEluY29tZSAsIGRkYXQkSW5jb21lX2NhdCApCgpkZGF0MiA8LWRkYXQKI2NvbFN1bXMoaXMubmEoZGRhdDIpKQoKCiMgYXNzaWduIG1lYW5pbmdmdWwgbGFiZWxzIHRvIEFnZQpkZGF0MiRBZ2UgPC0gZmFjdG9yKGRkYXQyJEFnZSwgCiAgbGV2ZWxzID0gMToxMywgCiAgbGFiZWxzID0gYygiMTgtMjQgeXJzIiwgIjI1LTI5IHlycyIsICIzMC0zNCB5cnMiLCAiMzUtMzkgeXJzIiwgIjQwLTQ0IHlycyIsIAogICAgICAgICAgICAgIjQ1LTQ5IHlycyIsICI1MC01NCB5cnMiLCAiNTUtNTkgeXJzIiwgIjYwLTY0IHlycyIsICI2NS02OSB5cnMiLCAKICAgICAgICAgICAgICI3MC03NCB5cnMiLCAiNzUtNzkgeXJzIiwgIjgwKyB5cnMiKSkKCgoKIyBCTUkgY2F0ZWdvcmllcwpkZGF0MiA8LSBkZGF0MiAlPiUKICBtdXRhdGUoQk1JX0NhdCA9IGN1dChCTUksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygwLCAxOC41LCAyNC45LCAyOS45LCBJbmYpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlVuZGVyd2VpZ2h0IiwgIk5vcm1hbCIsICJPdmVyd2VpZ2h0IiwgIk9iZXNlIikpKQoKCgojIFlFUy9OTyBsYWJlbHMKZGRhdDIgPC0gZGRhdDIgJT4lCiAgbXV0YXRlKAogICAgSGlnaENob2wgPSByZWNvZGUoSGlnaENob2wsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIEhpZ2hCUCA9IHJlY29kZShIaWdoQlAsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIFNtb2tlciA9IHJlY29kZShTbW9rZXIsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIFN0cm9rZSA9IHJlY29kZShTdHJva2UsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIEhlYXJ0RGlzZWFzZW9yQXR0YWNrID0gcmVjb2RlKEhlYXJ0RGlzZWFzZW9yQXR0YWNrLCAiMCIgPSAiTm8iLCAiMSIgPSAiWWVzIiksCiAgICBQaHlzQWN0aXZpdHkgPSByZWNvZGUoUGh5c0FjdGl2aXR5LCAiMCIgPSAiTm8iLCAiMSIgPSAiWWVzIiksCiAgICBGcnVpdHMgPSByZWNvZGUoRnJ1aXRzLCAiMCIgPSAiTm8iLCAiMSIgPSAiWWVzIiksCiAgICBWZWdnaWVzID0gcmVjb2RlKFZlZ2dpZXMsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKQogICkKCgojRGlhYmV0ZXMgc3RhdHVzLCBFZHVjYXRpb24gYW5kIEluY29tZSwgZXRjIGxhYmVscwpkZGF0MiA8LSBkZGF0MiAlPiUKICBtdXRhdGUoCiAgICBFZHVjYXRpb24gPSByZWNvZGUoRWR1Y2F0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiTm8gSGlnaCBTY2hvb2wiLCAKICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSAiU29tZSBIaWdoIFNjaG9vbCIsIAogICAgICAgICAgICAgICAgICAgICAgICIzIiA9ICJIaWdoIFNjaG9vbCBHcmFkdWF0ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICI0IiA9ICJTb21lIENvbGxlZ2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAiNSIgPSAiQ29sbGVnZSBHcmFkdWF0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgIjYiID0gIkNvbGxlZ2UgNCB5ZWFycyBvciBtb3JlIChDb2xsZWdlIGdyYWR1YXRlKSIpLAogICAgSW5jb21lID0gcmVjb2RlKEluY29tZSwgCiAgICAgICAgICAgICAgICAgICAgIjEiID0gIjwkMTBLIiwgCiAgICAgICAgICAgICAgICAgICAgIjIiID0gIiQxMEstJDE1SyIsIAogICAgICAgICAgICAgICAgICAgICIzIiA9ICIkMTVLLSQyNUsiLCAKICAgICAgICAgICAgICAgICAgICAiNCIgPSAiJDI1Sy0kMzVLIiwgCiAgICAgICAgICAgICAgICAgICAgIjUiID0gIiQzNUstJDUwSyIsIAogICAgICAgICAgICAgICAgICAgICI2IiA9ICIkNTBLLSQ3NUsiLCAKICAgICAgICAgICAgICAgICAgICAiNyIgPSAiPiQ3NUsiLAogICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gIlVua25vd24iKSwKICAgU2V4ID0gcmVjb2RlKFNleCwgCiAgICAgICAgICAgICAgICAgICIxIiA9ICJNYWxlIiwgCiAgICAgICAgICAgICAgICAgICIwIiA9ICJGZW1hbGUiLAogICAgICAgICAgICAgICAgLmRlZmF1bHQgPSAiVW5rbm93biIpLAogICBDaG9sQ2hlY2sgPSByZWNvZGUoQ2hvbENoZWNrLAogICAgICAgICAgICAgICAgICAgICAgIjEiID0gIlllcyIsCiAgICAgICAgICAgICAgICAgICAgICAiMCIgPSAiTm8iICksCiAgIAogICBEaWZmV2FsayA9IHJlY29kZShEaWZmV2FsaywKICAgICAgICAgICAgICAgICAgICAgICIxIiA9ICJZZXMiLAogICAgICAgICAgICAgICAgICAgICAgIjAiID0gIk5vIiApLAogIAogICBBbnlIZWFsdGhjYXJlID0gcmVjb2RlKEFueUhlYWx0aGNhcmUsCiAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiWWVzIiwKICAgICAgICAgICAgICAgICAgICAgICIwIiA9ICJObyIgKSwKCiAgIE5vRG9jYmNDb3N0ID0gcmVjb2RlKE5vRG9jYmNDb3N0LAogICAgICAgICAgICAgICAgICAgICAgIjEiID0gIlllcyIsCiAgICAgICAgICAgICAgICAgICAgICAiMCIgPSAiTm8iICksCiAgSHZ5QWxjb2hvbENvbnN1bXAgPSByZWNvZGUoSHZ5QWxjb2hvbENvbnN1bXAsCiAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiWWVzIiwKICAgICAgICAgICAgICAgICAgICAgICIwIiA9ICJObyIgKSwKICAgIERpYWJldGVzX2JpbmFyeSA9IHJlY29kZShEaWFiZXRlc19iaW5hcnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjAiID0gIk5vIERpYWJldGVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiSGFzIERpYWJldGVzIiksCiAgCiAgR2VuSGx0aCA9IHJlY29kZShHZW5IbHRoLAogICAgICAgICAgICAgICAgICAiMSIgPSAiRXhjZWxsZW50IiwKICAgICAgICAgICAgICAgICAgICIyIiA9ICJWZXJ5IEdvb2QiLAogICAgICAgICAgICAgICAgICAgIjMiID0gIkdvb2QiLAogICAgICAgICAgICAgICAgICAgIjQiID0gIkZhaXIiLAogICAgICAgICAgICAgICAgICAgIjUiID0gIlBvb3IiLAogICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSAiVW5rbm93biIpCiAgKQoKCgojdGFibGUgKGRkYXQyJEluY29tZSkKI3VuaXF1ZShkZGF0MiRJbmNvbWUpCgojIGNyZWF0ZSBzb21lIG1pc3NpbmcgZGF0YSBwb2ludHMgCiMgRGVmaW5lIHRoZSBwZXJjZW50YWdlIG9mIG1pc3NpbmcgdmFsdWVzIAptaXNzaW5nX3BlcmNlbnRhZ2UgPC0gMC4wNQoKIyBHZXQgdG90YWwgbnVtYmVyIG9mIHJvd3MKdG90YWxfcm93cyA8LSBucm93KGRkYXQyKQoKIyBBcHBseSBtaXNzaW5nIHZhbHVlcyB0byBhbGwgdmFyaWFibGVzCmRkYXQyIDwtIGRkYXQyICU+JQogIG11dGF0ZShhY3Jvc3MoZXZlcnl0aGluZygpLCB+IHsKICAgIG1pc3NfaWQgPC0gc2FtcGxlKDE6dG90YWxfcm93cywgc2l6ZSA9IHJvdW5kKG1pc3NpbmdfcGVyY2VudGFnZSAqIHRvdGFsX3Jvd3MpLCByZXBsYWNlID0gRkFMU0UpCiAgICAuW21pc3NfaWRdIDwtIE5BICAjIEFzc2lnbiBOQSB0byBzZWxlY3RlZCByb3dzCiAgICAuCiAgfSkpCgoKCgojIG92ZXJhbGwgc3VtbWFyeSBvZiB2YXJpYWJsZXMKbGlicmFyeShzdW1tYXJ5dG9vbHMpCmRmU3VtbWFyeShkZGF0MikKCiN0YWJsZShkZGF0MiRBZ2UpCiN0YWJsZShkZGF0MiRCTUlfQ2F0KQojc3VtbWFyeSAoZGRhdDIkQk1JKQpgYGAKCgoKYGBge3IgQk1JLCByZXN1bHRzPSdoaWRlJ30KIyBnZXQgZGF0YSBpbnRvIFIKI0JNSSB2YXJpYWJsZQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdyaWQpCmJtaTEgPC0gZ2dwbG90KGRkYXQyLCBhZXMoeCA9IEJNSSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiQk1JIERpc3RyaWJ1dGlvbiIsIHggPSAiQk1JIiwgeSA9ICJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKCmJtaTIgPC0gZ2dwbG90KGRkYXQyLCBhZXMoeCA9IEJNSSkpICsKICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJsaWdodGJsdWUiLCBhbHBoYSA9IDAuNikgKwogIGxhYnModGl0bGUgPSAiRGVuc2l0eSBQbG90IG9mIEJNSSIsIHggPSAiQk1JIiwgeSA9ICJEZW5zaXR5IikgKwogIHRoZW1lX21pbmltYWwoKQoKYm1pMyA8LSBnZ3Bsb3QoZGRhdDIsIGFlcyh5ID0gQk1JKSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gInRvbWF0byIsIGFscGhhID0gMC43LCBvdXRsaWVyLmNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIkJveHBsb3Qgb2YgQk1JIiwgeSA9ICJCTUkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpncmlkLmFycmFuZ2UoYm1pMSwgYm1pMiwgYm1pMywgbmNvbCA9IDIsIHRvcCA9IHRleHRHcm9iKCJPdmVydmlldyBvZiBCTUkiLCBncCA9IGdwYXIoZm9udHNpemUgPSAxNiwgZm9udGZhY2UgPSAiYm9sZCIpKSkgCgojY2hlY2sgc2tld25lc3Mgb2YgQk1JCmxpYnJhcnkoZTEwNzEpCnNrZXduZXNzKGRkYXQyJEJNSSwgbmEucm09VFJVRSkgCnNrZXduZXNzKGRkYXQyJEJNSSwgbmEucm09VFJVRSkgCgojIHJlbW92ZSBCTUkgb3V0bGllcnMKUTEgPC0gcXVhbnRpbGUoZGRhdDIkQk1JLCAwLjI1LCBuYS5ybSA9IFRSVUUpClEzIDwtIHF1YW50aWxlKGRkYXQyJEJNSSwgMC43NSwgbmEucm0gPSBUUlVFKQpJUVIgPC0gUTMgLSBRMQoKIyBEZWZpbmUgYWNjZXB0YWJsZSByYW5nZQpsb3dlcl9ib3VuZCA8LSBRMSAtIDEuNSAqIElRUgp1cHBlcl9ib3VuZCA8LSBRMyArIDEuNSAqIElRUgoKIyBSZW1vdmUgb3V0bGllcnMKZGRhdDMgPC0gZGRhdDJbZGRhdDIkQk1JID49IGxvd2VyX2JvdW5kICYgZGRhdDIkQk1JIDw9IHVwcGVyX2JvdW5kLCBdCgoKCiNwbG90IG9mIEJNSSB3aXRoIG91dGxpZXJzIHJlbW92ZWQ6IGRkYXQzIG5vdyBjb250YWlucyBkYXRhIHdpdGggbm8gb3V0bGllcnMKYm1pMTIgPC0gZ2dwbG90KGRkYXQzLCBhZXMoeCA9IEJNSSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiQk1JIERpc3RyaWJ1dGlvbiIsIHggPSAiQk1JIiwgeSA9ICJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKCmJtaTIyIDwtIGdncGxvdChkZGF0MywgYWVzKHggPSBCTUkpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAibGlnaHRibHVlIiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgUGxvdCBvZiBCTUkiLCB4ID0gIkJNSSIsIHkgPSAiRGVuc2l0eSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmJtaTMyIDwtIGdncGxvdChkZGF0MywgYWVzKHkgPSBCTUkpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAidG9tYXRvIiwgYWxwaGEgPSAwLjcsIG91dGxpZXIuY29sb3IgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBCTUkiLCB5ID0gIkJNSSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmdyaWQuYXJyYW5nZShibWkxMiwgYm1pMjIsIGJtaTMyLCBuY29sID0gMiwgdG9wID0gdGV4dEdyb2IoIk92ZXJ2aWV3IG9mIEJNSSB3aXRoIG5vIG91dGxpZXJzIiwgZ3AgPSBncGFyKGZvbnRzaXplID0gMTYsIGZvbnRmYWNlID0gImJvbGQiKSkpIAoKCiNjYXRlZ29yaXplZCBCTUkgYmFyIGNoYXJ0CmJtaWdycDwtIGdncGxvdChkZGF0MyAlPiUgZmlsdGVyKCFpcy5uYShCTUlfQ2F0KSksIGFlcyh4ID0gQk1JX0NhdCkpICsKICBnZW9tX2JhcihmaWxsID0gImxpZ2h0Ymx1ZSIgLCB3aWR0aCA9IDAuNikgKwogIGxhYnModGl0bGUgPSAiQk1JIENhdGVnb3JpZXMgRGlzdHJpYnV0aW9uIiwKICAgICAgIHggPSAiQk1JIGNhdGVnb3J5IiwKICAgICAgIHkgPSAiQ291bnQiCiAgICAgICApICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QubWFyZ2luID0gbWFyZ2luKDIsIDIsIDIsIDIpICkKICAKYm1pZ3JwCmBgYAoKICArIERpYWJldGVzIFN0YXR1czogSW4gdGhlIHNhbXBsZSwgbWFqb3JpdHkgb2YgdGhlIHBhcnRpY2lwYW50cyBkaWQgbm90IGhhdmUgZGlhYmV0ZXMoODYlKS4gT25seSBhIHNtYWxsZXIgcHJvcG9ydGlvbiB3aGVyZSBkaWFiZXRpYyBvciBoYWQgcHJlLWRpYWJldGVzLiBUaGlzIHN1Z2dlc3RzIGxvdyBwcmV2YWxlbmNlIG9mIGRpYWJldGVzIGluIG91ciBzYW1wbGUuIAogICsgTWVudGFsIEhlYWx0aDogSGlzdG9ncmFtIGFuZCBkZW5zaXR5IHBsb3RzIHNob3dlZCBmZXcgcGVvcGxlIGhhZCBmZXcgZGF5cyB3aXRoIHBvb3IgbWVudGFsIGhlYWx0aCB0aGUgbGFzdCAzMCBkYXlzIChtZWFuID0gYXBwcm94aW1hdGVseSAzIGRheXMgb2YgYmFkIG1lbnRhbCBoZWFsdGggZGF5cykuCiAgICBPdXRsaWVycyB3ZXJlIHJlcGxhY2VkIHdpdGggbWVhbiB2YWx1ZXMuCiAgKyBQaHlzaWNhbCBIZWFsdGggaW4gbGFzdCAzMCBkYXlzIGRpc3RyaWJ1dGlvbiBzaG93ZWQgb3V0bGllcnMgYW5kIHRoZXNlIHZhbHVlcyB3ZXJlIHJlcGxhY2VkIHdpdGggdGhlIG1lYW4uCiAgKyBHZW5lcmFsIEhlYWx0aCBTdGF0dXM6IE1vc3QgcGVvcGxlIHJlcG9ydGVkIHZlcnkgZ29vZCBvciBnb29kIGhlYWx0aCBzdGF0dXMgb3ZlcmFsbCB3aXRoIHNrZXduZXNzIG9ic2VydmVkIHRvd2FyZHMgcG9vciBoZWFsdGguIAogICAgYW5kIHNvIG5vIHNwZWNpYWwgY2hhbmdlcyB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHZhcmlhYmxlLiAKICArIEluY29tZSB2YXJpYWJsZSB3YXMgbmVnYXRpdmVseSBza2V3ZWQuIE1vc3QgcGFydGljaXBhbnRzIGVhcm5lZCBoaWdoZXIgaW5jb21lLiBUaGUgdmFyaWFibGUgaXMgY2F0ZWdvcml6ZWQgaW50byBMb3csIE1lZGl1bSwgYW5kIEhpZ2ggaW5jb21lIGxldmVscy4KICArIFNleDogTW9yZSBmZW1hbGVzIHBhcnRpY2lwYXRlZCBpbiB0aGUgc2FtcGxlIGRhdGEgdGhhbiBtYWxlcy4gCiAgKyBBZ2U6IERpc3RyaWJ1dGlvbiBvZiBhZ2Ugd2FzIHN1Y2ggdGhhdCBtYWpvcml0eSBvZiBwYXJ0aWNpcGFudHMgd2VyZSBiZXlvbmQgNDAgeWVhcnMgb2xkLiBUaGlzIHN1Z2dlc3RzIHRoYXQgbW9zdCBwYXJ0aWNpcGFudHMgd2VyZSBvbGRlciBhbmQgYWdlIHNob3VsZCAgICAgY29udHJvbGxlZCBmb3IgaW4gYW55IGFuYWx5c2lzLgogICsgRWR1Y2F0aW9uOiBNb3N0IG9mIHRoZSBwYXJ0aWNpcGFudHMgaGFkIGEgaGlnaCBzY2hvb2wgZGlwbG9tYSBvciBoaWdoZXIgKG92ZXIgODAlKS4gCiAgKyBIaWdoIGJsb29kIFByZXNzdXJlIGFuZCBIaWdoIENob2xlc3Rlcm9sOiBNb3JlIHBhcnRpY2lwYW50cyBkaWQgbm90IGhhdmUgaGlnaCBibG9vZCBwcmVzc3VyZSBhbmQgbW9yZSBkaWQgbm90IGhhdmUgYW55IGNob2xlc3Rlcm9sIGNoZWNrcyBpbiB0aGUgbGFzdCA1IHllYXJzLiAKICArIFNtb2tlcjogQWJvdXQgNDQlIG9mIHRoZSBwYXJ0aWNpcGFudHMgc21va2VkIGF0IGxlYXN0IDEwMCBjaWdhcmV0dGVzIGluIHRoZWlyIGVudGlyZSBsaWZldGltZS4gQ29uc2lkZXJpbmcgaG93IHNtb2tpbmcgYWZmZWN0cyBvdXIgaGVhbHRoIGFuZCB3aXRoIHN1Y2ggbWFueSBpbiAgICAgc2FtcGxlLCBjb250cm9sbGluZyBmb3IgdGhpcyB2YXJpYWJsZSBpbiBvdXIgYW5hbHlzaXMgYW5kIGV4cGxvcmluZyBob3cgdGhpcyB2YXJpYWJsZSBpbnRlcmFjdHMgd2l0aCBvdGhlcnMgdG8gaW1wYWN0IGRpYWJldGVzIHdpbGwgYmUgc3R1ZGllZC4KICArIEhlYXZ5IEFsY29ob2wgY29uc3VtcHRpb24gLSBib3RoIG1lbiBhbmQgd29tZW4gcmVwb3J0ZWQgdGhleSBhcmUgbm90IGhlYXZ5IGRyaW5rZXJzIGJ1dCB0aGVzZSBjb3VsZCBiZSBpbmNvcnJlY3QgcmVwcmVzZW50YXRpb24gZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhleSBtYXkgcmVwb3J0IGFzIG5vdCBoZWF2eSBkcmlua2VycyBmb3Igc29jaWFsbHkgZGVzaXJhYmxlIHJlc3BvbnNlcyBhbmQgZXhwZWN0YXRpb25zLiBUaGUgYW5hbHlzaXMgY2FuIGJlIGNvbmR1Y3RlZCBmb3IgbWVuIGFuZCB3b21lbiBzZXBhcmF0ZWx5IGFuZCBmb3IgdGhvc2Ugd2hvIHJlcG9ydGVkIGFzIGhlYXZ5IGRyaW5rZXJzIHRvIHVuY292ZXIgaGlkZGVuIHJlbGF0aW9ucy4gCiAgKyBIZWFydCBkaXNlYXNlL2F0dGFjayB3YXMgbm90IHByZXZhbGVudCBpbiBvdXIgc2FtcGxlLiBCdXQgd2Uga25vdyB0aGF0IGRpYWJldGVzIGltcGFjdHMgdGhlIGhlYXJ0IGZ1bmN0aW9uLCBpdCB3aWxsIGJlIGludGVyZXN0aW5nIHRvIHNlZSBpZiB0aG9zZSB3aG8gaGFkIGRpYWJldGVzIHJlcG9ydGVkIHRvIGF2ZSBoYWQgYW55IG9mIHRoZXNlIGNvbmRpdGlvbnMuIAogICsgU3Ryb2tlOiBNb3N0IHBlb3BsZSBoYWQgbmV2ZXIgYmVlbiB0b2xkIHRoZXkgaGFkIGRpYWJldGVzICg5NSUpLiAKICArIE90aGVyIHZhcmlhYmxlczogTW9zdCBwZW9wbGUgZGlkIG5vdCBoYXZlIGRpZmZpY3VsdHkgd2Fsa2luZyB1cCB0aGUgc3RhaXJzLCB3ZXJlIHBoeXNpY2FsbHkgYWN0aXZlIGluIHRoZSBwYXN0IDMwIGRheXMsIGhhZCBzb21lIGZvcm0gb2YgaGVhbHRoIGluc3VyYW5jZSBhbmQgY291bGQgc2VlIGEgZG9jdG9yIHdoZW4gbmVlZGVkLCBjb25zdW1lZCB2ZWdldGFibGVzIG9uY2Ugb3IgbW9yZSB0aW1lcyBhIGRheSwgYnV0IHNsaWdodGx5IG1vcmUgZGlkIG5vdCBjb25zdW1lIGZydWl0cyBhdCB0aGUgc2FtZSByYXRlIGFzIHZlZ2V0YWJsZXMuCgpgYGB7ciBNZW5ILCByZXN1bHRzPSdoaWRlJ30KIyBEaWFiZXRlcyBTdGF0dXMKZ2dwbG90KGRkYXQzICU+JSBmaWx0ZXIoIWlzLm5hKERpYWJldGVzX2JpbmFyeSkpLCBhZXMoeCA9IGZhY3RvcihEaWFiZXRlc19iaW5hcnkpKSkgKwogIGdlb21fYmFyKGZpbGwgPSAibGlnaHRibHVlIiAsIHdpZHRoID0gMC40KSArCiAgbGFicyh0aXRsZSA9ICJEaWFiZXRlcyBTdGF0dXMiLAogICAgICAgeCA9ICJEaWFiZXRlcyBTdGF0dXMiLAogICAgICAgeSA9ICJDb3VudCIKICAgICAgICkgKwogIHRoZW1lX2NsYXNzaWMoKSsKICB0aGVtZShwbG90Lm1hcmdpbiA9IG1hcmdpbigyLCAyLCAyLCAyKSApCgojUGVyY2VudGFnZXMgd2l0aGluIGRpYWJldGVzCkRpYWIucGVyY2VudGFnZXMgPC0gZGRhdDMgJT4lCiAgY291bnQoRGlhYmV0ZXNfYmluYXJ5KSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IG4gLyBzdW0obikgKiAxMDApCkRpYWIucGVyY2VudGFnZXMKCiNNZW50YWwgSGVhbHRoIFZhcmlhYmxlcwpzdW1tYXJ5KGRkYXQzJE1lbnRIbHRoKQptZW5oMSA8LSBnZ3Bsb3QoZGRhdDIsIGFlcyh4ID0gTWVudEhsdGgpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAieWVsbG93IiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgUGxvdCBvZiBub3QgZ29vZCBtZW50YWwgaGVhbHRoIGRheXMiLCB4ID0gIk1lbnRhbCBIZWFsdGgiLCB5ID0gIkRlbnNpdHkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKbWVuaDIgIDwtIGdncGxvdChkZGF0MywgYWVzKHggPSBNZW50SGx0aCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAieWVsbG93IiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIG5vdCBnb29kIG1lbnRhbCBoZWFsdGggZGF5cyIsIHggPSAiRGF5cyIsIHkgPSAiQ291bnQiKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKbWVuaDMgPC0gZ2dwbG90KGRkYXQzLCBhZXMoeSA9IE1lbnRIbHRoKSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gInllbGxvdyIsIGFscGhhID0gMC43LCBvdXRsaWVyLmNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIkJveHBsb3Qgb2YgTnVtYmVyIG9mIGRheXMgTWVudGFsIGhlYWx0aCB3YXMgbm90IGdvb2QiLCB5ID0gIk1lbnRhbCBIZWFsdGggRGF5cyIpICsKICB0aGVtZV9taW5pbWFsKCkKCgpncmlkLmFycmFuZ2UobWVuaDEsIG1lbmgyLCBtZW5oMywgbmNvbCA9IDIsIHRvcCA9IHRleHRHcm9iKCJPdmVydmlldyBvZiBNZW50YWwgSGVhbHRoIGluIFBhc3QgMzAgRGF5cyIsIGdwID0gZ3Bhcihmb250c2l6ZSA9IDE2LCBmb250ZmFjZSA9ICJib2xkIikpKSAKCiMgRGVmaW5lIGEgZnVuY3Rpb24gdG8gcmVwbGFjZSBvdXRsaWVycyB3aXRoIHRoZSBtZWFuCnJlcGxhY2Vfb3V0bGllcnNfd2l0aF9tZWFuIDwtIGZ1bmN0aW9uKHgpIHsKICBRMSA8LSBxdWFudGlsZSh4LCAwLjI1LCBuYS5ybSA9IFRSVUUpCiAgUTMgPC0gcXVhbnRpbGUoeCwgMC43NSwgbmEucm0gPSBUUlVFKQogIElRUiA8LSBRMyAtIFExCiAgCiAgIyBEZWZpbmUgbG93ZXIgYW5kIHVwcGVyIGJvdW5kcwogIGxvd2VyX2JvdW5kIDwtIFExIC0gMS41ICogSVFSCiAgdXBwZXJfYm91bmQgPC0gUTMgKyAxLjUgKiBJUVIKICAKICAjIFJlcGxhY2Ugb3V0bGllcnMgd2l0aCB0aGUgbWVhbgogIHhbeCA8IGxvd2VyX2JvdW5kIHwgeCA+IHVwcGVyX2JvdW5kXSA8LSBtZWFuKHgsIG5hLnJtID0gVFJVRSkKICAKICByZXR1cm4oeCkKfQoKIyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gbWVudGFsIGhlYWx0aCB0byByZXBsYWNlIG91dGxpZXJzIHdpdGggbWVhbiB2YWx1ZQpkZGF0MyRNZW50SGx0aCA8LSByZXBsYWNlX291dGxpZXJzX3dpdGhfbWVhbihkZGF0MyRNZW50SGx0aCkKCiNQaHlzaWNhbCBIZWFsdGggaGlzdG9ncmFtClBoICA8LSBnZ3Bsb3QoZGRhdDMsIGFlcyh4ID0gUGh5c0hsdGgpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjcpICsKICBsYWJzKHRpdGxlID0gIlBoeXNpY2FsIEhlYWx0aCBEYXlzIiwgeCA9ICJEYXlzIiwgeSA9ICJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKI1BoCgojIEFwcGx5IHRoZSBmdW5jdGlvbiB0byBtZW50YWwgaGVhbHRoIHRvIHJlcGxhY2Ugb3V0bGllcnMgd2l0aCBtZWFuIHZhbHVlCmRkYXQzJFBoeXNIbHRoIDwtIHJlcGxhY2Vfb3V0bGllcnNfd2l0aF9tZWFuKGRkYXQzJFBoeXNIbHRoKQoKI2NhdGVnb3JpemVkIEdlbmVyYWwgSGVhbHRoIGJhciBjaGFydApkZGF0MyA8LSBkZGF0MyAlPiUKICBtdXRhdGUoR2VuSGx0aCA9IGZhY3RvcihHZW5IbHRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJQb29yIiwgIkZhaXIiLCAiR29vZCIsICJWZXJ5IEdvb2QiLCAiRXhjZWxsZW50IiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgIApHaCA8LSBnZ3Bsb3QoZGRhdDMgJT4lIGZpbHRlcighaXMubmEoR2VuSGx0aCkpLCBhZXMoeCA9IEdlbkhsdGgpKSArCiAgZ2VvbV9iYXIoZmlsbCA9ICJibHVlIiwgd2lkdGggPTAuNCkgKwogIGxhYnModGl0bGUgPSAiR2VuZXJhbCBIZWFsdGggU3RhdHVzIiwKICAgICAgIHggPSAiR2VuZXJhbCBIZWFsdGgiLAogICAgICAgeSA9ICJDb3VudCIKICAgICAgICkgKwogIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLjEsIDAuMSkpKwogIHRoZW1lX2NsYXNzaWMoKQpHaAoKCiNjYXRlZ29yaXplZCBTZXggY2hhcnQKU2V4IDwtIGdncGxvdChkZGF0MyAlPiUgZmlsdGVyKCFpcy5uYShTZXgpKSwgYWVzKHggPSBTZXgpKSArCiAgZ2VvbV9iYXIoZmlsbCA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiR2VuZGVyIiwKICAgICAgIHggPSAiR2VuZGVyIiwKICAgICAgIHkgPSAiQ291bnQiCiAgICAgICApICsKICB0aGVtZV9jbGFzc2ljKCkKI1NleAp1bmlxdWUoZGRhdDMkU2V4KTsKCiMgQWdlIEdyb3VwcwpBZ2UgPC0gZ2dwbG90KGRkYXQyICU+JSBmaWx0ZXIoIWlzLm5hKEFnZSkpLCBhZXMoeCA9IEFnZSkpICsKICBnZW9tX2JhcihmaWxsID0gImJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJBZ2UgZ3JvdXAgQmFyIENoYXJ0IiwKICAgICAgIHggPSAiQWdlIEdyb3VwIiwKICAgICAgIHkgPSAiQ291bnQiCiAgICAgICApICsKICB0aGVtZV9jbGFzc2ljKCkKI0FnZQoKQWdlLnBlcmNlbnRhZ2VzIDwtIGRkYXQgJT4lCiAgY291bnQoQWdlKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IG4gLyBzdW0obikgKiAxMDApCkFnZS5wZXJjZW50YWdlcwoKIyBFZHVjYXRpb24KRWR1LnBlcmNlbnRhZ2VzIDwtIGRkYXQgJT4lCiAgY291bnQoRWR1Y2F0aW9uKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IG4gLyBzdW0obikgKiAxMDApCkVkdS5wZXJjZW50YWdlcwoKIyBTbW9rZXIKU21va2UucGVyY2VudGFnZXMgPC0gZGRhdCAlPiUKICBjb3VudChTbW9rZXIpICU+JQogIG11dGF0ZShQZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkKU21va2UucGVyY2VudGFnZXMKCiMgU3Ryb2tlClN0cm9rZS5wZXJjZW50YWdlcyA8LSBkZGF0ICU+JQogIGNvdW50KFN0cm9rZSkgJT4lCiAgbXV0YXRlKFBlcmNlbnRhZ2UgPSBuIC8gc3VtKG4pICogMTAwKQpTdHJva2UucGVyY2VudGFnZXMKCmBgYAoKClwKCiMjIDQuIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIEZlYXR1cmVzIC0gQml2YXJpYXRlCgpcCldlIHdpbGwgbm93IGV4cGxvcmUgYW5kIGhhdmUgdmlzdWFsaXphdGlvbnMgb2YgcmVsYXRpb25zaGlwcyBhbW9uZyBzZXZlcmFsIHZhcmlhYmxlcyBpbiBvdXIgc2FtcGxlIGRhdGEuIFdlIHdpbGwgYmUgbG9va2luZyBhdCB2aXN1YWxzIGZvciB0d28gb3IgbW9yZSBudW1lcmljYWwgZmVhdHVyZSB2YXJpYWJsZXMsIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbmQgdmlzdWFscyB0aGF0IGxvb2sgY29tYmluYXRpb25zIG9mIHRoZXNlIHRvIGFpZCBpbiBvdXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgZGF0YSBhbmQgaG93IGl0IGluZmx1ZW5jZXMgb3VyIHVuZGVyc3RhbmRpbmcgb2YgaG93IHRvIGFwcHJvYWNoIGFuYWx5c2lzIG9mIHRoZSBkYXRhLiAKCiAgKyBEaWFiZXRlcyBhbmQgQk1JIHBsb3RzIDogVGhlIGJveCBwbG90IHNob3dpbmcgdGhlIGRpYWJldGVzIGFuZCBCTUkgcGxvdCBzaG93cyB0aGUgbWVkaWFuIEJNSSBpbiB0aGUgZGlhYmV0aWMgZ3JvdXAgaXMgaGlnaGVyIHN1Z2dlc3RzIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIAogICAgdGhlc2UgMiB2YXJpYWJsZXMuIEFkZGl0aW9uYWxseSwgdGhlIGRlbnNpdHkgcGxvdCBzaG93cyBoaWdoZXIgQk1JIGluIHRoZSBkaWFiZXRpYyBncm91cCB0aGFuIHRoZSBub24tZGlhYmV0aWMgZ3JvdXAuCiAgKyBEaWFiZXRlcyBhbmQgUGh5c2ljYWwgQWN0aXZpdHkgcGxvdDogVGhlIGJpdmFyaWF0ZSBwbG90IHNob3dzIHRoYXQgd2hpbGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwaHlzaWNhbCBhY3Rpdml0eSBpbiB0aGUgcGFzdCAzMCBkYXlzIGlzIHNpbWlsYXIsIGZhciBsZXNzICAgICAgICAKICAgIGRpYWJldGljIHBlb3BsZSB3ZXJlIHBoeXNpY2FsbHkgYWN0aXZlIGluIHRoZSBsYXN0IDMwIGRheXMuCgoKCgpgYGB7ciB0d292YXIsIHJlc3VsdHM9J2hpZGUnfQojIyMjIyMjIyMjIHR3byB2YXJpYWJsZSByZWxhdGlvbnNoaXBzCgojIGRpYWJldGVzIGFuZCBCTUkKIApnZ3Bsb3QoZGRhdDMlPiUgZmlsdGVyKCFpcy5uYShEaWFiZXRlc19iaW5hcnkpKSwgYWVzKHggPSBmYWN0b3IoRGlhYmV0ZXNfYmluYXJ5KSwgeSA9IEJNSSwgZmlsbCA9IGZhY3RvcihEaWFiZXRlc19iaW5hcnkpKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBsYWJzKHRpdGxlID0gIkJNSSBEaXN0cmlidXRpb24gYnkgRGlhYmV0ZXMgU3RhdHVzIiwKICAgICAgIHggPSAiRGlhYmV0ZXMgU3RhdHVzIiwKICAgICAgIHkgPSAiQk1JIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJncmVlbiIpKSArCiAgdGhlbWVfY2xhc3NpYygpKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCmdncGxvdChkZGF0MyU+JSBmaWx0ZXIoIWlzLm5hKERpYWJldGVzX2JpbmFyeSkpLCBhZXMoeCA9IEJNSSwgZmlsbCA9IGZhY3RvcihEaWFiZXRlc19iaW5hcnkpKSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQk1JIERlbnNpdHkgUGxvdCBieSBEaWFiZXRlcyBTdGF0dXMiLAogICAgICAgeCA9ICJCTUkiLAogICAgICAgeSA9ICJEZW5zaXR5IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJncmVlbiIpKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCgoKI2RpYWJldGVzIGFuZCBwaHlzaWNhbCBoZWFsdGgKCmdncGxvdChkZGF0MyU+JSBmaWx0ZXIoIWlzLm5hKERpYWJldGVzX2JpbmFyeSkgJiAhaXMubmEoUGh5c0FjdGl2aXR5KSksIGFlcyh4ID0gZmFjdG9yKERpYWJldGVzX2JpbmFyeSksIGZpbGwgPSBmYWN0b3IoUGh5c0FjdGl2aXR5KSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBsYWJzKHRpdGxlID0gIkdyb3VwZWQgQmFyIFBsb3Qgb2YgRGlhYmV0ZXMgU3RhdHVzIGFuZCBQaHlzaWNhbCBBY3Rpdml0eSBpbiBwYXMgMzAgZGF5cyIsCiAgICAgICB4ID0gIkRpYWJldGVzIFN0YXR1cyIsCiAgICAgICB5ID0gIkNvdW50IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImJsdWUiLCAicmVkIiwgImdyZWVuIikpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJQeXNpY2FsbHkgQWN0aXZlIGxhc3QgMzAgZGF5cyIpKSArCiAgdGhlbWVfY2xhc3NpYygpCiAgCgojY29sbmFtZXMoZGRhdDMpCgpgYGAKCgoKYGBge3IgbXVsdGl2YXJ9CiNjb3JyZWxhdGlvbiBwbG90IG9mIG51bWVyaWNhbCB2YXJpYWJsZXMKbGlicmFyeShnZ2NvcnJwbG90KQpzZWxlY3RfdmFycyA8LSBjKCJQaHlzSGx0aCIsICJNZW50SGx0aCIsICJHZW5IbHRoIiwgIkJNSSIpCmNvcnJfbWF0cml4IDwtIGNvcihkZGF0ICU+JSBzZWxlY3QoYWxsX29mKHNlbGVjdF92YXJzKSksIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQoKIyBDb252ZXJ0IG1hdHJpeCB0byBsb25nIGZvcm1hdApjb3JyX21lbHQgPC0gbWVsdChjb3JyX21hdHJpeCkKCiMgUGxvdCBoZWF0bWFwCiMgUGxvdCB3aXRoIHRleHQgbGFiZWxzCmNvcjEgPC0gZ2dwbG90KGNvcnJfbWVsdCwgYWVzKHggPSBWYXIxLCB5ID0gVmFyMiwgZmlsbCA9IHZhbHVlKSkgKwogIGdlb21fdGlsZSgpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQodmFsdWUsIDIpKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkgKyAgIyBBZGQgdmFsdWVzCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIG1pZHBvaW50ID0gMCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJDb3JyZWxhdGlvbiBIZWF0bWFwIiwgZmlsbCA9ICJDb3JyZWxhdGlvbiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKI2luc3RhbGwucGFja2FnZXMoImNvcnJwbG90IikKbGlicmFyeShjb3JycGxvdCkKCmNvcnJwbG90KGNvcnJfbWF0cml4LCBtZXRob2QgPSAiY29sb3IiLCB0eXBlID0gInVwcGVyIiwKICAgICAgICAgY29sID0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKSgyMDApLAogICAgICAgICB0bC5jZXggPSAwLjcsIHRsLmNvbCA9ICJibGFjayIsCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwgbnVtYmVyLmNleCA9IDAuOCkgICMgQWRkIHZhbHVlcwoKCiNpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdGx5KQp1bmlxdWUoZGRhdDMkSW5jb21lX2NhdCkKbXljb2xvcnMgPC0gYygiTG93IiA9ICJyZWQiLCAiTWVkaXVtIiA9ICJvcmFuZ2UiLCAiSGlnaCIgPSAiZ3JlZW4iLCAiVmVyeSBIaWdoIiA9ICJibHVlIikKCmdncGxvdGx5X2RlbnNpdHkgPC0gZGRhdDMlPiUgZmlsdGVyKCFpcy5uYShJbmNvbWVfY2F0KSAmICFpcy5uYShEaWFiZXRlc19iaW5hcnkpKSAgJT4lIAogIGdncGxvdChhZXMoeCA9IEJNSSwgY29sb3IgPSBJbmNvbWVfY2F0LCBmaWxsID0gSW5jb21lX2NhdCkpICsKICBnZW9tX2RlbnNpdHkobGluZXdpZHRoID0gMC43NSwgYWxwaGEgPSAwLjYpICsKICB4bGFiKCJCTUkgSW5kZXgiKSArIAogIGxhYnMoY29sb3IgPSAiSW5jb21lIEdyb3VwcyIsIGZpbGwgPSAiSW5jb21lIEdyb3VwcyIpICsKICBnZ3RpdGxlKCJEZW5zaXR5IEN1cnZlIG9mIEJNSSBhY3Jvc3MgSW5jb21lIEdyb3VwcyIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXljb2xvcnMpICsgICMgQ3VzdG9tIGxpbmUgY29sb3JzCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbXljb2xvcnMpICsgICMgQ3VzdG9tIGZpbGwgY29sb3JzCiAgICAgICAgICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMiwxLDIsMSksICJjbSIpLAogICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICArIAogIGZhY2V0X3dyYXAofiBEaWFiZXRlc19iaW5hcnkpICAjIFNwbGl0IGJ5IGRpYWJldGVzIHN0YXR1cwoKZ2dwbG90bHkoZ2dwbG90bHlfZGVuc2l0eSkKCgoKbXljb2xvcnMubiA8LSBjKCJQb29yIiA9ICJyZWQiLCAiRmFpciIgPSAib3JhbmdlIiwgIkdvb2QiID0gImdyZWVuIiwgIlZlcnkgR29vZCIgPSAiYmx1ZSIsICJFeGNlbGxlbnQiID0gImxpZ2h0Ymx1ZSIpCmdncGxvdGx5X2RlbnNpdHkubiA8LSBkZGF0MyU+JSBmaWx0ZXIoIWlzLm5hKEdlbkhsdGgpICYgIWlzLm5hKERpYWJldGVzX2JpbmFyeSkpICAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gQk1JLCBjb2xvciA9IEdlbkhsdGgsIGZpbGwgPSBHZW5IbHRoKSkgKwogIGdlb21fZGVuc2l0eShsaW5ld2lkdGggPSAwLjc1LCBhbHBoYSA9IDAuNikgKwogIHhsYWIoIkJNSSBJbmRleCIpICsgCiAgbGFicyhjb2xvciA9ICJHZW5lcmFsIEhlYWx0aCIsIGZpbGwgPSAiR2VuZXJhbCBIZWFsdGgiKSArCiAgZ2d0aXRsZSgiRGVuc2l0eSBDdXJ2ZSBvZiBCTUkgYWNyb3NzIEdlbmVyYWwgSGVhbHRoIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteWNvbG9ycy5uKSArICAjIEN1c3RvbSBsaW5lIGNvbG9ycwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15Y29sb3JzLm4pICsgICMgQ3VzdG9tIGZpbGwgY29sb3JzCiAgICAgICAgICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMiwxLDIsMSksICJjbSIpLAogICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICArIAogIGZhY2V0X3dyYXAofiBEaWFiZXRlc19iaW5hcnkpICAjIFNwbGl0IGJ5IGRpYWJldGVzIHN0YXR1cwoKZ2dwbG90bHkoZ2dwbG90bHlfZGVuc2l0eS5uKQoKCgpgYGAKCgpcCgojIyA1LiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBGZWF0dXJlcyAtIE11dGxpdmFyaWF0ZSAKClwKVGhlIGRlbnNpdHkgcGxvdCBvZiBCTUkgYW5kIEluY29tZSBncm91cHMgc2hvd3MgdGhhdCBCTUkgaXMgaGlnaGVzdCBpbiBtb3JlIHBhcnRpY2lwYW50cyBpbiB0aGUgbG93IGFuZCBtZWRpdW0gaW5jb21lIGdyb3Vwcy4gQW5kIHBhcnRpY2lwYW50cyBpbiB0aGUgdmVyeSBoaWdoIGluY29tZSBncm91cCBhcmUgYW1vbmcgdGhvc2Ugd2l0aCBCTUkgbGVzcyB0aGFuIDMwIG9yIGhlYWx0aGllci4gV2hlbiB0aGUgcGxvdCBpcyBzcGxpdCBieSBkaWFiZXRlcyBzdGF0dXMsIHdlIG9ic2VydmVkIHNpbWlsYXIgZGlzdHJpYnV0aW9uIGJ1dCB3ZSBzZWUgdGhhdCB2YXJpYW5jZSBpbiB0aGUgaW5jb21lIGdyb3VwcyBpcyBub3QgYXMgZGlzdGluY3QgZm9yIGhpZ2ggYW5kIHZlcnkgaGlnaCBncm91cHMuIFdoaWxlIGhpZ2hlciBCTUkgaXMgY29tb24gaW4gYWxsIGRpYWJldGljcywgaXQgaXMgbW9yZSBjb21tb24gaW4gdGhlIExvdyBhbmQgTWVkaXVtIGluY29tZSBncm91cHMgYW5kIGluZGljYXRlcyBzb21lIHZhcmlhYmlsaXR5IGluIHRoZSB0aGUgZGlhYmV0aWMgZ3JvdXAuIFNpbWlsYXIgcGF0dGVybnMgd2VyZSBvYnNlcnZlZCBhbW9uZyBnZW5lcmFsIGhlYWx0aCBzdGF0dXMgd2l0aCB0aG9zZSBpbiB0aGUgcG9vciBoZWFsdGggc3RhdHVzIGFsc28gd2l0aCBoaWdoZXIgQk1JIGJvdGggaW4gdGhlIGRpYWJldGljIGFuZCBub24tZGlhYmV0aWMgZ3JvdXBzLiBUaGUgc2hpZnQgaW4gcGVha3MgaW4gYm90aCBkZW5zaXR5IHBsb3RzIHN1Z2dlc3RzIGFzc29jaWF0aW9ucyBiZXR3ZWVuIGRpYWJldGVzIGFuZCBCTUkgd2hpY2ggZGlmZmVycyBhbW9uZyBkaWZmZXJlbnQgaW5jb21lIGFuZCBoZWFsdGggZ3JvdXBzLiAKCgo=